gpt4 book ai didi

c# - 如何画线并在面板中选择它

转载 作者:行者123 更新时间:2023-12-04 00:37:54 25 4
gpt4 key购买 nike

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

private List<Point> coordFirst = new List<Point>();
private List<Point> coordLast = new List<Point>();
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<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))));

这是点击十字线的结果:

enter image description here

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

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 类,因为它不是双缓冲。而是使用 PictureBoxLabel(使用 AutoSize=false)或 doublebuffered Panel 子类:

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

注释:

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

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

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

  • 是的,对于像一行这样简单的东西来说,Line 类看起来有点长,但是看看现在所有的事件代码有多短!那是因为责任就在他们所属的地方!

  • 另请注意,在 WinForms 中进行任何绘图的首要规则是:从不缓存或存储 Grahics 对象。事实上,您一开始就不应该使用 CreateGraphics,因为 Graphics 对象永远不会停留在范围内,并且它生成的图形将不坚持(即在最小化-最大化序列中幸存下来)..

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

  • 要选择较细的线条,稍微修改一下距离检查可能会有所帮助。

  • 数学直接取自 Wikipedia .

关于c# - 如何画线并在面板中选择它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32919918/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com