如何画线并在Panel中选择它

我的程序可以使用canvas.Drawline()绘制线条。 如何点击线并更改此颜色(选择线)?

private List coordFirst = new List(); private List coordLast = new List(); public Graphics canvas; private void Form1_Load(object sender, EventArgs e) { canvas=panel1.CreateGraphics(); } 

存储在coordFirs和coodLast中的坐标线。

这是一个合适的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 lines = new List(); 

以下是如何使用以下几行初始化它:

 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)))); 

这是点击十字路口的结果:

在此处输入图像描述

每当您添加,更改或删除一行时,您需要通过触发Paint事件使Panel反映新闻:

 panel1.Invalidate(); 

这是PanelPaint事件:

 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 。 而是使用PictureBoxdoublebuffered Panel子类:

 class DrawPanel : Panel { public DrawPanel () { DoubleBuffered = true; } } 

备注

  • 在WinForms中没有“Line”这样的东西,只有各种颜色的像素。 因此,要选择一条线,您需要存储它的两个端点的坐标,然后找出您是否在点击时点击它。

  • 上面的例子展示了如何在数学中做到这一点。

  • 相反,可以通过将每条线绘制到位图上来测试每条线并测试鼠标单击的像素。 但绘制这些位图也必须在幕后进行数学运算,并为位图分配空间,因此数学效率会更高。

  • 是的, Line类看起来有点像线条那样简单,但看看现在所有的事件代码有多短! 那是因为责任是他们所属的地方!

  • 另请注意,在WinForms中执行任何绘图的第一条规则是: 永远不要缓存或存储Grahics对象。 实际上你不应该首先使用 CreateGraphics ,因为Graphics对象永远不会留在范围内,它产生的图形将不会持久存在 (即在最小化最大化序列中存活)。

  • 另请注意我如何将Paint事件参数的e.Graphics对象传递Line实例,以便他们可以使用当前Graphics对象绘制自己!

  • 要选择较细的线条,可能有助于稍微修改距离检查..

  • 数学直接取自维基百科 。

您可以在点击时更改所有内容的颜色。 通过使用特定对象的单击事件。

我给你一个按钮的例子。 如果单击按钮,则会更改panal的颜色。 您可以根据需要修改代码。

 private List coordFirst = new List(); private List coordLast = new List(); public Graphics canvas; private void Form1_Load(object sender, EventArgs e) { canvas = panel1.CreateGraphics(); } private void panel1_Click(object sender, EventArgs e) { panel1.BackColor = Color.Blue; } private void nonSelectableButton3_Click(object sender, EventArgs e) { panel1.BackColor = Color.BurlyWood; }