首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PaintEvent不过度涂装

PaintEvent不过度涂装
EN

Stack Overflow用户
提问于 2012-10-29 20:25:46
回答 3查看 1.3K关注 0票数 2

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

当您单击该按钮时,您可以为2个随机点绘制一条线。

代码语言:javascript
复制
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(); 
  }
} 

这个程序有一些缺陷:

  • 当你画一条线时,它会显示出来,只有当主窗口移到某个地方时(通常是当我隐藏它时)。
  • 它只能画一条线。

对如何修复这些错误有什么建议吗?

编辑

我读过你的答案并做了一些修改:

代码语言:javascript
复制
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。fine事件可以执行多行操作,但只有起点才行。不知何故,终点并不是很正确。我可以在哪里准确地设置MouseMove事件的最后一点?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-10-29 20:28:36

您必须调用面板上的失效方法:

代码语言:javascript
复制
private void drawPanel_MouseUp(object sender, MouseEventArgs e)
{
  onMouseUpFlag = true;
  drawPanel.Invalidate();
}

另外,使用PaintEvent中的图形对象:

代码语言:javascript
复制
private void drawPanel_Paint(object sender, PaintEventArgs e)
{
  if (onMouseUpFlag)
  {
    e.Graphics.DrawLine(p, ps, pe); 
  }
} 

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

根据您更新的代码,下面是我认为您正在尝试的工作示例:

代码语言:javascript
复制
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);
  }

}

使用inherited panel打开DoubleBuffer属性以避免闪烁。

票数 3
EN

Stack Overflow用户

发布于 2012-10-29 20:29:25

无论何时您想要重绘(在代码中),您都应该调用drawPanel.Invalidate()使其失效。

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

代码语言:javascript
复制
private void drawPanel_MouseUp(object sender, MouseEventArgs e)
{
            onMouseUpFlag = true;
            drawPanel.Invalidate();
}

最后,我建议在您的drawPanel_Paint中使用此代码,而不是您的代码。您应该使用EventArgs提供的图形,而不是创建新的图形。

代码语言:javascript
复制
private void drawPanel_Paint(object sender, PaintEventArgs e)
{
            if (onMouseUpFlag)
            {
                  e.Graphics.DrawLine(p, ps, pe); 
            }
}
票数 1
EN

Stack Overflow用户

发布于 2012-10-29 20:32:00

  1. 在鼠标松开之后,您需要触发一个重新绘制事件。只需调用drawPanel.Invalidate()就可以重新绘制表单。
  2. 要绘制多条线,您必须将每条线的信息存储在列表或其他内容中,并在重绘中绘制每条线。油漆方法基本上每次都以空白开始,因此它将只绘制当前设置它的最新方式。
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13129089

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档