PaintEvent没有覆盖

我在C#中有一个Windows窗体应用程序,带有绘图面板和一个按钮 – 用于绘制线条。

单击该按钮时,可以绘制2个随机点的直线。

Pen p = new Pen(Color.Black, 5); //point for start Point ps = new Point(); //point for end Point pe = new Point(); private void drawPanel_MouseDown(object sender, MouseEventArgs e) { ps.X = eX; ps.Y = eY; pe = ps; } private void drawPanel_MouseMove(object sender, MouseEventArgs e) { // when button is clicked for drawing draw = true; if (draw) { if (e.Button == MouseButtons.Left) { pe = new Point(eX, eY); } } } private void drawPanel_MouseUp(object sender, MouseEventArgs e) { onMouseUpFlag = true; } private void drawPanel_Paint(object sender, PaintEventArgs e) { Graphics g = drawPanel.CreateGraphics(); if (onMouseUpFlag) { g.DrawLine(p, ps, pe); g.Dispose(); } } 

该计划有一些缺陷:

  • 当你绘制一条线时,只有当主窗口被移动到某处时(通常是当我隐藏它时)它才会显示它
  • 它只能画1行。

有任何建议如何修复这些错误?

编辑

我已经读了你的答案并做了一些改变:

 Pen p = new Pen(Color.Black, 5); Point ps = new Point(); Point pe = new Point(); List linesStart= new List(); List linesEnd= new List(); private void drawPanel_MouseDown(object sender, MouseEventArgs e) { ps.X = eX; ps.Y = eY; linesStart.Add(ps); pe = ps; } private void drawPanel_MouseMove(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { pe = new Point(eX, eY); //adding end point .. actually adds a lot of points linesEnd.Add(pe); } } bool onMouseUpFlag = false; private void drawPanel_MouseUp(object sender, MouseEventArgs e) { onMouseUpFlag = true; drawPanel.Invalidate(); } private void drawPanel_Paint(object sender, PaintEventArgs e) { if (onMouseUpFlag) { for (int i = 0; i < linesStart.Count; i++) { e.Graphics.DrawLine(p, linesStart[i], linesEnd[i]); } } } 

现在我正在尝试为多行修复DrawLine。 Paint事件可以做多行,但只有起点可以。 不知怎的,终点不是很正确。 我可以在哪里准确设置MouseMove事件的最后一点?

您必须在面板上调用Invalidate方法:

 private void drawPanel_MouseUp(object sender, MouseEventArgs e) { onMouseUpFlag = true; drawPanel.Invalidate(); } 

另外,使用PaintEvent中的Graphic对象:

 private void drawPanel_Paint(object sender, PaintEventArgs e) { if (onMouseUpFlag) { e.Graphics.DrawLine(p, ps, pe); } } 

对于多行,您必须保持集合对象中的点。

根据您更新的代码,以下是我认为您尝试执行的操作示例:

 private class Line { public Point Starting { get; set; } public Point Ending { get; set; } public Line(Point starting, Point ending) { this.Starting = starting; this.Ending = ending; } } List lines = new List(); private Point downPoint = Point.Empty; private Point movePoint = Point.Empty; private bool movingLine = false; public Form1() { InitializeComponent(); panel1.Paint += panel1_Paint; panel1.MouseDown += panel1_MouseDown; panel1.MouseMove += panel1_MouseMove; panel1.MouseUp += panel1_MouseUp; } void panel1_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { downPoint = e.Location; } } void panel1_MouseMove(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { movingLine = true; movePoint = e.Location; panel1.Invalidate(); } } void panel1_MouseUp(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { movingLine = false; lines.Add(new Line(downPoint, e.Location)); panel1.Invalidate(); } } void panel1_Paint(object sender, PaintEventArgs e) { e.Graphics.Clear(Color.White); foreach (Line l in lines) { e.Graphics.DrawLine(Pens.Black, l.Starting, l.Ending); } if (movingLine) { e.Graphics.DrawLine(Pens.Black, downPoint, movePoint); } } 

使用inheritance的面板打开DoubleBuffer属性以避免闪烁。

每当你想重绘(在你的代码中)你应该调用panelinvalidate drawPanel.Invalidate()

当您完成鼠标移动并释放按钮时

 private void drawPanel_MouseUp(object sender, MouseEventArgs e) { onMouseUpFlag = true; drawPanel.Invalidate(); } 

最后我建议在你的drawPanel_Paint中使用这个代码而不是你的代码。 您应该使用EventArgs提供的Graphics,而不是创建新的。

 private void drawPanel_Paint(object sender, PaintEventArgs e) { if (onMouseUpFlag) { e.Graphics.DrawLine(p, ps, pe); } } 
  1. 放下鼠标后需要触发重绘事件。 只需调用drawPanel.Invalidate()以重新绘制表单。

  2. 要绘制多行,您必须将每个行的信息存储在列表或其他内容中,并在绘制中绘制每一行。 Paint方法基本上每次都以空格开头,因此它只会以您当前设置的方式绘制最新的方式。