テキストボックスから入力された数値で座標をとり、線を書く への返答
投稿で使用できる特殊コードの説明。(別タブで開きます。)
以下の返答は逆順(新しい順)に並んでいます。
投稿者 ゆうさく  (社会人)
投稿日時
2018/6/10 21:38:42
教えていただいたのを参考にし、3つ 座標を入れて△を描くこうとするとおかしなことになります
座標 (150,100)(100,200)(300,200)を入力してるんですけれども
実施すると (0,0)(100,200)(300,200)
の3点を結んだ三角形になっています。
(150,100)(100,200)(300,200)
この3つを結んだ三角形を作りたいです。
For i = 0 To maxIndex - 1
For j = i + 1 To maxIndex
If i <> j Then
g.DrawLine(Pens.Black, zahyo(i), zahyo(j))
End If
Next
Next
予想なんですけれども
例えば
i = 0 の時 g.DrawLine(Pens.Black, zahyo(0), zahyo(1))
i = 1 の時 g.DrawLine(Pens.Black, zahyo(1), zahyo(2))
i = 2 の時 g.DrawLine(Pens.Black, zahyo(2), zahyo(3))
になっていると思います
i = 2 の時に g.DrawLine(Pens.Black, zahyo(0), zahyo(2))
にしたいんですけど、どこを修正すればいいでしょうか?
Public Class Form1
Private zahyo(8) As Point
Private Sub txt()
zahyo(0).X = Val(TextBox1.Text)
zahyo(0).Y = Val(TextBox2.Text)
zahyo(1).X = Val(TextBox3.Text)
zahyo(1).Y = Val(TextBox4.Text)
zahyo(2).X = Val(TextBox5.Text)
zahyo(2).Y = Val(TextBox6.Text)
zahyo(3).X = Val(TextBox7.Text)
zahyo(3).Y = Val(TextBox8.Text)
zahyo(4).X = Val(TextBox9.Text)
zahyo(4).Y = Val(TextBox10.Text)
zahyo(5).X = Val(TextBox11.Text)
zahyo(5).Y = Val(TextBox12.Text)
zahyo(6).X = Val(TextBox13.Text)
zahyo(6).Y = Val(TextBox14.Text)
zahyo(7).X = Val(TextBox15.Text)
zahyo(7).Y = Val(TextBox16.Text)
End Sub
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)
Call txt()
Dim maxIndex As Integer = zahyo.Length - 1
For i = 0 To maxIndex - 1
For j = i + 1 To maxIndex
If i <> j Then
g.DrawLine(Pens.Black, zahyo(i), zahyo(j))
End If
Next
Next
PictureBox1.Image = canvas
End Sub
End Class
座標 (150,100)(100,200)(300,200)を入力してるんですけれども
実施すると (0,0)(100,200)(300,200)
の3点を結んだ三角形になっています。
(150,100)(100,200)(300,200)
この3つを結んだ三角形を作りたいです。
For i = 0 To maxIndex - 1
For j = i + 1 To maxIndex
If i <> j Then
g.DrawLine(Pens.Black, zahyo(i), zahyo(j))
End If
Next
Next
予想なんですけれども
例えば
i = 0 の時 g.DrawLine(Pens.Black, zahyo(0), zahyo(1))
i = 1 の時 g.DrawLine(Pens.Black, zahyo(1), zahyo(2))
i = 2 の時 g.DrawLine(Pens.Black, zahyo(2), zahyo(3))
になっていると思います
i = 2 の時に g.DrawLine(Pens.Black, zahyo(0), zahyo(2))
にしたいんですけど、どこを修正すればいいでしょうか?
Public Class Form1
Private zahyo(8) As Point
Private Sub txt()
zahyo(0).X = Val(TextBox1.Text)
zahyo(0).Y = Val(TextBox2.Text)
zahyo(1).X = Val(TextBox3.Text)
zahyo(1).Y = Val(TextBox4.Text)
zahyo(2).X = Val(TextBox5.Text)
zahyo(2).Y = Val(TextBox6.Text)
zahyo(3).X = Val(TextBox7.Text)
zahyo(3).Y = Val(TextBox8.Text)
zahyo(4).X = Val(TextBox9.Text)
zahyo(4).Y = Val(TextBox10.Text)
zahyo(5).X = Val(TextBox11.Text)
zahyo(5).Y = Val(TextBox12.Text)
zahyo(6).X = Val(TextBox13.Text)
zahyo(6).Y = Val(TextBox14.Text)
zahyo(7).X = Val(TextBox15.Text)
zahyo(7).Y = Val(TextBox16.Text)
End Sub
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)
Call txt()
Dim maxIndex As Integer = zahyo.Length - 1
For i = 0 To maxIndex - 1
For j = i + 1 To maxIndex
If i <> j Then
g.DrawLine(Pens.Black, zahyo(i), zahyo(j))
End If
Next
Next
PictureBox1.Image = canvas
End Sub
End Class
投稿者 魔界の仮面弁士  (社会人)
投稿日時
2018/6/7 13:19:04
> 両方のパターンで書いてみました。
すべての点を繋ぐ場合のコードを、少し修正。
> For i = 0 To maxIndex
> For j = 0 To maxIndex
これだと、A⇒B 方向の線分と B⇒A 方向の線分が重ねて描画されてしまうので
For i = 0 To maxIndex - 1
For j = i + 1 To maxIndex
の方が良さそうです。
すべての点を繋ぐ場合のコードを、少し修正。
> For i = 0 To maxIndex
> For j = 0 To maxIndex
これだと、A⇒B 方向の線分と B⇒A 方向の線分が重ねて描画されてしまうので
For i = 0 To maxIndex - 1
For j = i + 1 To maxIndex
の方が良さそうです。
投稿者 (削除されました)  ()
投稿日時
2018/6/7 13:16:03
(削除されました)
投稿者 魔界の仮面弁士  (社会人)
投稿日時
2018/6/7 11:58:32
提示頂いたプログラムが不完全なので、やりたいことが曖昧になってしまっています。(End Sub は書き忘れかだろうと思いますが)
たとえば、Bitmap を生成していますが、それを表示したり保存したりするコードが無いですよね。
結果として、生成した Bitmap や Graphics を破棄することもせず、単に作り続けて放置するだけのプログラムになっています。
一応、Form1 の Paint イベントで処理しているという事は、Form1 上に描画したいのだと思いますが、そのような画面設計だと、TextBox が描画領域に重なって配置され、邪魔になってしまうと思います。
「Form ではなく PictureBox への描画に切り替える」か「座標入力フォームと描画先のフォームを別画面にする」などした方が良いかもしれません。
> を繰り返しの処理でまとめたいです
TextBox のかわりに、DataGridView などを使うようにするか、
もしくは、代入式の右辺も配列にする(TextBox の配列)と良いでしょう。
> g.DrawLine(Pens.Black, zahyou(0), zahyou(0))
> ようにzahyouがかぶらないようにもしたいのですが
3 座標の場合は△を描くとして…。
4 座標の場合は□を描くのか☒を描くのかが分からなかったので、両方のパターンで書いてみました。
> よろしくお願いいたします。
サンプルを書いてみました。
http://www.vb-user.net/junk/replySamples/2018.06.07.11.55/Sample30338.zip
お使いの VB バージョンが分からなかったので、
比較的古めのバージョン(VB2008)で作成してあります。
たとえば、Bitmap を生成していますが、それを表示したり保存したりするコードが無いですよね。
結果として、生成した Bitmap や Graphics を破棄することもせず、単に作り続けて放置するだけのプログラムになっています。
一応、Form1 の Paint イベントで処理しているという事は、Form1 上に描画したいのだと思いますが、そのような画面設計だと、TextBox が描画領域に重なって配置され、邪魔になってしまうと思います。
「Form ではなく PictureBox への描画に切り替える」か「座標入力フォームと描画先のフォームを別画面にする」などした方が良いかもしれません。
> を繰り返しの処理でまとめたいです
TextBox のかわりに、DataGridView などを使うようにするか、
もしくは、代入式の右辺も配列にする(TextBox の配列)と良いでしょう。
> g.DrawLine(Pens.Black, zahyou(0), zahyou(0))
> ようにzahyouがかぶらないようにもしたいのですが
3 座標の場合は△を描くとして…。
4 座標の場合は□を描くのか☒を描くのかが分からなかったので、両方のパターンで書いてみました。
Dim maxIndex As Integer = zahyo.Length - 1
For i = 0 To maxIndex
For j = 0 To maxIndex
If i <> j Then
e.Graphics.DrawLine(Pens.Black, zahyo(i), zahyo(j))
End If
Next
Next
Dim maxIndex As Integer = zahyo.Length - 1
For i = 1 To maxIndex
e.Graphics.DrawLine(Pens.Black, zahyo(i - 1), zahyo(i))
Next
If maxIndex > 0 Then
e.Graphics.DrawLine(Pens.Black, zahyo(maxIndex), zahyo(0))
End If
> よろしくお願いいたします。
サンプルを書いてみました。
http://www.vb-user.net/junk/replySamples/2018.06.07.11.55/Sample30338.zip
お使いの VB バージョンが分からなかったので、
比較的古めのバージョン(VB2008)で作成してあります。
投稿者 ゆうさく  (社会人)
投稿日時
2018/6/6 19:01:17
コードは下記です
Public Class Form1
Private zahyou(2) As Point
Private Sub txt()
zahyou(0).X = Val(TextBox1.Text)
zahyou(0).Y = Val(TextBox2.Text)
zahyou(1).X = Val(TextBox3.Text)
zahyou(1).Y = Val(TextBox4.Text)
zahyou(2).X = Val(TextBox5.Text)
zahyou(2).Y = Val(TextBox6.Text)
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)
Call txt()
For i As Integer = 1 To zahyou.Count - 1
g.DrawLine(Pens.Black, zahyou(0), zahyou(1))
Next
End Sub
やりたいことは2つあります
1つめは
zahyou(0).X = Val(TextBox1.Text)
zahyou(0).Y = Val(TextBox2.Text)
・
・
・
・
を繰り返しの処理でまとめたいです
2つめは
g.DrawLine(Pens.Black, zahyou(0), zahyou(1))
g.DrawLine(Pens.Black, zahyou(1), zahyou(2))
g.DrawLine(Pens.Black, zahyou(0), zahyou(2))
今は勉強のためzahyouのところを固定にしているんですけれども
これも繰り返しの処理でまとめたいです。
zahyou()←の中に何を入れていいのかわかりません。
例えば
g.DrawLine(Pens.Black, zahyou(0), zahyou(0))
ようにzahyouがかぶらないようにもしたいのですが
調べてみても思いつきませんでした。
よろしくお願いいたします。
Public Class Form1
Private zahyou(2) As Point
Private Sub txt()
zahyou(0).X = Val(TextBox1.Text)
zahyou(0).Y = Val(TextBox2.Text)
zahyou(1).X = Val(TextBox3.Text)
zahyou(1).Y = Val(TextBox4.Text)
zahyou(2).X = Val(TextBox5.Text)
zahyou(2).Y = Val(TextBox6.Text)
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)
Call txt()
For i As Integer = 1 To zahyou.Count - 1
g.DrawLine(Pens.Black, zahyou(0), zahyou(1))
Next
End Sub
やりたいことは2つあります
1つめは
zahyou(0).X = Val(TextBox1.Text)
zahyou(0).Y = Val(TextBox2.Text)
・
・
・
・
を繰り返しの処理でまとめたいです
2つめは
g.DrawLine(Pens.Black, zahyou(0), zahyou(1))
g.DrawLine(Pens.Black, zahyou(1), zahyou(2))
g.DrawLine(Pens.Black, zahyou(0), zahyou(2))
今は勉強のためzahyouのところを固定にしているんですけれども
これも繰り返しの処理でまとめたいです。
zahyou()←の中に何を入れていいのかわかりません。
例えば
g.DrawLine(Pens.Black, zahyou(0), zahyou(0))
ようにzahyouがかぶらないようにもしたいのですが
調べてみても思いつきませんでした。
よろしくお願いいたします。
> 座標 (150,100)(100,200)(300,200)を入力してるんですけれども
それだと、座標が「3 つ」しか無いですよね。
TextBox の数が幾つであろうと、提示頂いたコードにおいては、
最終的に座標を管理しているのは
> Private zahyo(8) As Point
という、zahyo(0)~zahyo(8) の「9 つの座標」であるはずです。
> 実施すると (0,0)(100,200)(300,200)
> の3点を結んだ三角形になっています。
テキストボックスの入力値にとらわれず、
変数 zahyo に代入された 9 つの値を確認してみてください。
その中に、(0, 0) を保存しているデータが混入してはいませんでしたか?
(0, 0) が紛れ込んでいたなら、(0, 0) を結ぶ線分が描画されるのは当然の結果なので、
まずは (0, 0) が含まれていないことを確認するのが先決です。
もし、9 つすべてを使いたいわけのではなく、3 つだけでよいのなら、
案1) zahyo 配列は 9 つにせず、3 つにしておく(あるいは動的に増減させる)
案2)「使わない座標」と「(0, 0) という座標」を区別できるよう管理方法を見直す
などを再検討してみてください。
> 予想なんですけれども
『予想』するだけで終えず、きちんと『確認』しておきましょう。
ステップ実行で一行ずつ処理を追い、それぞれの変数に
どのような値が代入されているのか確認すれば、予想が正しいかどうか分かりますよね。
http://rucio.a.la9.jp/main/dotnet/shokyu/standard41.htm
> zahyo(0).X = Val(TextBox1.Text)
「zahyo(0).X = Val(TextBox1.Text)」のような変換は望ましくありません。
Val ではなく、Integer.TryParse を使うようにしましょう。
If Integer.TryParse(TextBox1.Text, zahyo(0).X)
Val による変換結果は Double 型です。しかし、代入先となる、zahyo(0).X の型は
Integer 型なので、代入式の左右でデータ型が不一致になってしまっているからです。
また、Val 関数をさけるべき利用はもう一つあります。Val 関数は、
Val("99.8%") → InvalidCastException
Val("1.8E308") → OverflowException
のように、引き渡す文字列によってはエラーになってしまう可能性があるためです。
TryParse なら、どのような文字列を渡してもエラーにはなりませんし、
入力値が "" の場合と "0" の場合を区別して処理させることもできます。
> 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)
このコードも悪手です。Paint イベントで Bitmap や Grapchis を作り直すべきではありません。
Paint イベントを使う場合は、e.Graphics に対して描画を行うようにすべきです。
(先週、るきおさんが書かれたサンプルコードもそうなっていましたよね)
もし、Bitmap を毎回生成するのなら、それは Paint イベントが呼ばれたタイミングではなく、
座標値が変更された場合に行うべきです。座標値が変化しない限りは、
Bitmap を描きなおす必要も無いのですから。
また、Bitmap や Graphics を作り直すにしても、作ったまま放置するのではなく、
未使用になったオブジェクトは、Dispose メソッド(あるいは Using ブロック)を用いて
破棄するようにすべきです。