イベントを呼び出し への返答
投稿で使用できる特殊コードの説明。(別タブで開きます。)
以下の返答は逆順(新しい順)に並んでいます。
投稿者 るきお  (社会人)
投稿日時
2018/6/6 08:16:24
ゆうさくさんのプログラムがうまく動かない理由が不正確でしたので補足します。
(ゆうさくさんのプログラムではなく、私が少しいじってみたプログラムをもとに書いてしまいました。)
ゆうさくさんのプログラムがエラーになら直接的な理由は型変換ができないからです。
Form1_Paintの第2引数はPaintEventArgs型です。
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
ゆうさくさんはこれを下記のように呼び出そうとしています。
Call Form1_Paint(Me, EventArgs.Empty)
この第2引数はEventArgs型です。
EventArgs型からPaintEventArgs型への型変換は定義されていないためエラーになります。
一般的に、型Aから型Bに変換をする場合、
型Aと型Bが異なっていても、下記の場合成功します。
・型Bが型Aの基底クラスの場合。
・型Bが型Aが実装しているインターフェースの場合。
例外として特別に型変換がプログラムされている場合(=CTypeがオーバーロードされている場合)も型変換は成功します。
今回はこのどれでもないので失敗します。
次のプログラムで確認できます。
ちなみに Nothing は必ず代入できるので、
Call Form1_Paint(Me, Nothing)
ならば呼び出す自体は可能です。
(ゆうさくさんのプログラムではなく、私が少しいじってみたプログラムをもとに書いてしまいました。)
ゆうさくさんのプログラムがエラーになら直接的な理由は型変換ができないからです。
Form1_Paintの第2引数はPaintEventArgs型です。
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
ゆうさくさんはこれを下記のように呼び出そうとしています。
Call Form1_Paint(Me, EventArgs.Empty)
この第2引数はEventArgs型です。
EventArgs型からPaintEventArgs型への型変換は定義されていないためエラーになります。
一般的に、型Aから型Bに変換をする場合、
型Aと型Bが異なっていても、下記の場合成功します。
・型Bが型Aの基底クラスの場合。
・型Bが型Aが実装しているインターフェースの場合。
例外として特別に型変換がプログラムされている場合(=CTypeがオーバーロードされている場合)も型変換は成功します。
今回はこのどれでもないので失敗します。
次のプログラムで確認できます。
Dim typeA As EventArgs = EventArgs.Empty
Dim typeB As PaintEventArgs = Nothing
typeB = typeA
ちなみに Nothing は必ず代入できるので、
Call Form1_Paint(Me, Nothing)
ならば呼び出す自体は可能です。
投稿者 るきお  (社会人)
投稿日時
2018/6/6 07:28:19
できるだけ近い構造で実現しようとするとこのようになります。
ゆうさくさんのプログラムでは、canvasとPictureBoxが関連付けられていないため、canvasに描画してもPicturBoxは無反応です。
g.DrawLineのすぐ下に次の行を挿入すると線は描かれます。
PictureBox1.Image = canvas
でも、Form1のPaintイベントにプログラムが書かれているので、ボタンのクリック時ではなく、フォームの描画時に実行されてしまいます。
また、フォームの描画時に毎回canvasを生成してPictureBoxと関連付けるのは非効率です。
これらを改善すると上記のようになります。
なお、下記のような作り方もあります。
このプログラムはPictureBoxの描画にPictureBoxのPaintイベントを使用しており素直な作りです。
このつくりの良いところは、ボタンを押すたびにまっさらなところから描画を開始するので(といって人間には一瞬のできごとです)、動的に変化する図形を描画しやすいことです。
たとえば、マウスやキーボードなどの操作に追従してグラフィックスが変化していく場合は、こちらの作りの方がやりやすいです。
Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown
'ShownはForm1が初めて表示されるときに1回だけ実行されます。
'このタイミングでPictureBoxとBitmapを関連付けます。
'引数は描画領域の幅と高さ
canvas = New Bitmap(PictureBox1.Width, PictureBox1.Height)
PictureBox1.Image = canvas
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
'関連付けられたBitmapに描画します。
Dim g As Graphics = Graphics.FromImage(canvas)
g.DrawLine(Pens.Black, a, b, c, d)
'Bitmapの内容が変わってもPictureBox1は自動的に気が付いてくれないので、
'一旦現状の表示をリセットして関連付けられたBitmapを表示してもらいます。
PictureBox1.Invalidate()
End Sub
ゆうさくさんのプログラムでは、canvasとPictureBoxが関連付けられていないため、canvasに描画してもPicturBoxは無反応です。
g.DrawLineのすぐ下に次の行を挿入すると線は描かれます。
PictureBox1.Image = canvas
でも、Form1のPaintイベントにプログラムが書かれているので、ボタンのクリック時ではなく、フォームの描画時に実行されてしまいます。
また、フォームの描画時に毎回canvasを生成してPictureBoxと関連付けるのは非効率です。
これらを改善すると上記のようになります。
なお、下記のような作り方もあります。
Private Lines As New List(Of Rectangle)
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Lines.Add(New Rectangle(a, b, c, d))
PictureBox1.Invalidate()
End Sub
Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
For Each line As Rectangle In Lines
e.Graphics.DrawLine(Pens.Black, line.X, line.Y, line.X + line.Width, line.Y + line.Height)
Next
End Sub
このプログラムはPictureBoxの描画にPictureBoxのPaintイベントを使用しており素直な作りです。
このつくりの良いところは、ボタンを押すたびにまっさらなところから描画を開始するので(といって人間には一瞬のできごとです)、動的に変化する図形を描画しやすいことです。
たとえば、マウスやキーボードなどの操作に追従してグラフィックスが変化していく場合は、こちらの作りの方がやりやすいです。
投稿者 ゆうさく  (社会人)
投稿日時
2018/6/5 21:10:41
ボタンをクリック時にピクチャボックスに線が描画されるように作りたいのですが
どうしていいかわかりません。コードは下記です。
エラーになる理由とどうすれば描画のイベントを呼び出せるか教えてください
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
Dim canvas As New Bitmap(PictureBox1.Width, PictureBox1.Height)
Dim g As Graphics = Graphics.FromImage(canvas)
g.DrawLine(Pens.Black, a, b, c, d)
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Call Form1_Paint(Me, EventArgs.Empty)
End Sub
参考にさせていただきます