| ■103812 / ) |
Re[15]: Visual Basicで簡易CADを作成 |
□投稿者/ 魔界の仮面弁士 (3881回)-(2025/08/04(Mon) 19:43:28)
|
■No103811 (shiro さん) に返信 > Private Sub PictureBox1_MouseDown( > ByVal sender As System.Object, > ByVal e As System.Windows.Forms.MouseEventArgs) _ > Handles PictureBox1.MouseDown > > Dim pillarList As New List(Of Pillar)
Sub や Function の内側で Dim 宣言された変数を「ローカル変数」と呼びます。
そのデータ型が Integer であれ List であれ String であれ、 上記のローカル変数は、MouseDown イベントが発生するたびに初期化され MouseDown イベントを抜けるたびに破棄されてしまいます。
※変数の有効期間のことを、専門用語で「スコープ」と呼びます。
> Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint > Dim pillarList As New List(Of Pillar)
Paint イベントで宣言された pillarList 変数と MouseDown イベントで宣言された pillarList 変数は 名前が同じというだけで、それぞれ別物です。
描画オブジェクトの List は、各イベント間で共有されるべきものですから、 ローカル変数として「Dim pillarList As New List(Of Pillar)」などと宣言するのではなく、 フィールド変数として宣言するようにしてください。
つまり、従来の Private pointList As New List(Of Point) Private snappedRectangles As New List(Of Rectangle) と同様に、Form1 の直下にて Private pillarList As New List(Of Pillar) として宣言されるべきである、ということです。
これは、クラスを自作していなかったとしても同じことです。
スコープの概念は、Visual Basic の言語仕様として重要な所なので、 もしも御存知なかったのであれば Visual Basic 中学校の 初級講座 [改訂版] 第9回 変数のスコープと寿命 https://www.umayadia.com/VBStandard2/VBStandard2Toc.htm などで学んでおきましょう。
> Dim pillarList As New List(Of Pillar) > Dim newPillar As New Pillar With { > .Index = pillarList.Count + 1, > .X = SnapToGrid(e.Location).X, > .Y = SnapToGrid(e.Location).Y > } > pillarList.Add(newPillar)
これだと、Index 管理に問題があります。 No103805 で 柱B を削除した時のことを覚えていますか?
たとえば、柱が 3 本あった場合、それぞれの Index は 柱A ⇒ pillarList(0).Index は 1 柱B ⇒ pillarList(1).Index は 2 柱C ⇒ pillarList(2).Index は 3 と追加されていくことを想定されているのかと思います。
ではここで、柱A を削除したとすると 柱B ⇒ pillarList(0).Index は 2 柱C ⇒ pillarList(1).Index は 3 に変わるわけですよね。
ではその後、さらに柱D を建てるときに .Index = pillarList.Count + 1 が実行されたらどうなるでしょう? pillarList には柱が 2 本しかないので 柱B ⇒ pillarList(0).Index は 2 柱C ⇒ pillarList(1).Index は 3 柱D ⇒ pillarList(2).Index は 3 になってしまうわけです。
柱に固定的な番号を付けるのであれば、同じ Index 番号が再利用されることは防ぐべきなので、 例えばこのような書き方もしてみてください。
Public Class Pillar Private Shared LastIndex As Integer = 0 Public ReadOnly Property Index As Integer Public Property X As Integer Public Property Y As Integer
Public Sub New(location As Point) LastIndex += 1 Me.Index = LastIndex Me.X = location.x Me.Y = location.y End Sub End Class
そして、柱を建てる際には Dim newPillar As New Pillar(SnapToGrid(e.Location)) pillarList.Add(newPillar) のようにします。こうすれば Index も自動採番されますし、 pillarList から柱が削除された後も、Index の重複が発生することがありません。
|
|