這裏是一個適合Line
類:
class Line
{
public Color LineColor { get; set; }
public float Linewidth { get; set; }
public bool Selected { get; set; }
public Point Start { get; set; }
public Point End { get; set; }
public Line(Color c, float w, Point s, Point e)
{ LineColor = c; Linewidth = w; Start = s; End = e; }
public void Draw(Graphics G)
{ using (Pen pen = new Pen(LineColor, Linewidth)) G.DrawLine(pen, Start, End); }
public bool HitTest(Point Pt)
{
// test if we fall outside of the bounding box:
if ((Pt.X < Start.X && Pt.X < End.X) || (Pt.X > Start.X && Pt.X > End.X) ||
(Pt.Y < Start.Y && Pt.Y < End.Y) || (Pt.Y > Start.Y && Pt.Y > End.Y))
return false;
// now we calculate the distance:
float dy = End.Y - Start.Y;
float dx = End.X - Start.X;
float Z = dy * Pt.X - dx * Pt.Y + Start.Y * End.X - Start.X * End.Y;
float N = dy * dy + dx * dx;
float dist = (float)(Math.Abs(Z)/Math.Sqrt(N));
// done:
return dist < Linewidth/2f;
}
}
定義爲線名單,可能在類級別:
List<Line> lines = new List<Line>();
這裏是你如何能與一些初始化行:
for (int i = 0; i < 20; i++) lines.Add(new Line(Color.Black, 4f,
new Point(R.Next(panel1.Width), R.Next(panel1.Height)),
new Point(R.Next(panel1.Width), R.Next(panel1.Height))));
這裏是點擊一個交叉的結果:
panel1.Invalidate();
:
無論何時添加,更改或刪除,你需要做的Panel
行通過觸發Paint
事件反映新聞
這裏是Panel
的Paint
事件:
private void panel1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
foreach (Line L in lines) L.Draw(e.Graphics);
}
在MouseClick
事件中,你做了測試:
private void panel1_MouseClick(object sender, MouseEventArgs e)
{
foreach(Line L in lines)
L.LineColor = L.HitTest(e.Location) ? Color.Red : Color.Black;
panel1.Invalidate();
}
避免閃爍不使用基本Panel
類,因爲它不是doublebuffered
。相反,使用一個PictureBox
或doublebuffered Panel
子類:
class DrawPanel : Panel
{ public DrawPanel() { DoubleBuffered = true; } }
注意:
沒有所謂的 '行' 中的WinForms,只有各種顏色的像素沒有這樣的事情。因此,選擇一條線需要存儲兩個端點的座標,然後確定點擊時是否點擊了它。
上面的例子顯示瞭如何在數學中做到這一點。
取而代之,可以通過將每條線繪製到位圖上並測試鼠標點擊的像素來測試每條線。但是,繪製這些位圖將不得不在幕後進行數學計算,併爲位圖分配空間,所以數學計算效率會更高。
是的Line
類對於這樣一個簡單的事情看起來有點長,但看看現在所有的事件代碼有多短!這是因爲責任是他們所屬的地方!
還要注意在的WinForms做任何繪畫的第一條規則是:決不緩存或存儲Grahics
對象。其實你不應該永遠使用CreateGraphics
擺在首位,爲Graphics
對象將永遠留在範圍和它產生的圖形不會堅持(即生存最小化,最大化序列)..
另外請注意我如何通過出e.Graphics
對象的Paint
事件的參數Line
實例,以便他們可以使用當前的Graphics
對象繪製自己!
要選擇較細的線,它可以幫助來修改距離檢查一點...
數學運算直接採取形成Wikipedia。
來源
2015-10-03 09:17:23
TaW
你在靶向:的WinForms? WPF? ASP? ...? __Always__相應地標記您的問題! - 如果是WinForrms,這裏有兩個提示:1)__NEVER__嘗試緩存一個Graphics對象! __NEVER__! - 所有繪圖都必須使用'Paint'事件參數的e.Graphics對象! - 2)Winforms中沒有「線條」,只有各種顏色的像素。因此,要選擇一條線,您需要存儲兩個端點的座標,然後確定點擊時是否點擊了它。這可以用數學或通過查看像素來完成。爲獲得更好的建議,我們需要更多關於您的目標的信 – TaW
進行必要的數學見[這裏](https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line#Line_defined_by_two_points)! - 而不是使用兩個啞列表,你應該定義一個Line類,其中應包含所有信息,比如顏色,寬度,選擇狀態,以及使用Graphics obejct和方法來繪製它們的方法,以查看Point是否在其上! – TaW