PaintEvent不会过度绘制 [英] PaintEvent not overpainting

查看:210
本文介绍了PaintEvent不会过度绘制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在C#中有一个Windows Forms应用程序,带有绘图面板和一个按钮-用于绘制线条.

I have a Windows Forms application in C# with drawing panel and a button - for drawing a line.

单击按钮时,您可以绘制2个随机点的线.

When you click the button, you can draw a line for 2 random points.

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 = e.X;
  ps.Y = e.Y;
  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(e.X, e.Y);
    }
  }
}

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

该程序有一些缺陷:

  • 当您绘制一条线时,仅当主窗口移动时,它才会显示它 某个地方(通常是我藏起来的时候)
  • 它只能画一条线.
  • When you draw a line it shows it, only if the main window is moved somewhere(usually when I hide it)
  • It can draw only 1 line.

任何建议如何解决这些错误?

Any suggestions how to fix these bugs ?

编辑

我已经阅读了您的答案并进行了一些更改:

I've read you answers and made some changes :

Pen p = new Pen(Color.Black, 5); 
Point ps = new Point();
Point pe = new Point();

List<Point> linesStart= new List<Point>();
List<Point> linesEnd= new List<Point>();

private void drawPanel_MouseDown(object sender, MouseEventArgs e)
{
  ps.X = e.X;
  ps.Y = e.Y;

  linesStart.Add(ps);

  pe = ps;
}

private void drawPanel_MouseMove(object sender, MouseEventArgs e)
{
  if (e.Button == MouseButtons.Left)
  {
    pe = new Point(e.X, e.Y);

    //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事件的最后一点?

Now I'm trying to fix the DrawLine for multiple lines. Paint event can do multiple line but only the starting point is fine. Somehow the end point is not very correct. Where I can set exactly the last point of the MouseMove event ?

推荐答案

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

You have to call the Invalidate method on the panel:

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

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

Also, use the Graphic object from the PaintEvent:

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

对于多行,您必须将点保留在集合对象中.

For multiple lines, you would have to hold the points in a collection object.

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

Per your updated code, here is a working example of what I think you are trying to do:

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<Line> lines = new List<Line>();

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

}

使用继承的面板打开DoubleBuffer属性,以避免闪烁.

Use an inherited panel to turn on the DoubleBuffer property to avoid flickering.

这篇关于PaintEvent不会过度绘制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆