C# 油漆事件不过量

C# 油漆事件不过量,c#,winforms,panel,C#,Winforms,Panel,我有一个用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) {

我有一个用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 = 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(); 
  }
} 
该程序有一些缺陷:

  • 当你画一条线时,只有当主窗口被移动时,它才会显示出来 某处(通常是我藏起来的时候)
  • 它只能画一条线
有没有关于如何修复这些bug的建议

编辑

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

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]);
    } 
  }
} 
Pen p=新笔(颜色:黑色,5);
点ps=新点();
点pe=新点();
列表行开始=新建列表();
List linesEnd=新列表();
私有void drawPanel_MouseDown(对象发送器,MouseEventArgs e)
{
ps.X=e.X;
ps.Y=e.Y;
linesStart.Add(ps);
pe=ps;
}
私有void drawPanel_MouseMove(对象发送器,MouseEventArgs e)
{
if(e.Button==MouseButtons.Left)
{
pe=新点(e.X,e.Y);
//添加终点..实际上添加了很多点
linesEnd.Add(pe);
}
}
bool onMouseUpFlag=false;
私有void drawPanel_MouseUp(对象发送器,MouseEventArgs e)
{
onMouseUpFlag=true;
drawPanel.Invalidate();
}
私有void drawPanel_Paint(对象发送器、PaintEventArgs e)
{ 
如果(onMouseUpFlag)
{
对于(int i=0;i

现在我正在尝试修复多条线的抽绳。绘制事件可以绘制多条直线,但只有起点可以。不知何故,终点并不十分正确。在那里我可以精确地设置MouseMove事件的最后一个点

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

private void drawPanel_MouseUp(object sender, MouseEventArgs e)
{
  onMouseUpFlag = true;
  drawPanel.Invalidate();
}
另外,使用PaintEvent中的图形对象:

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

}
私有类行{
公共点起点{get;set;}
公共点结尾{get;set;}
公共线路(起点、终点){
这个。开始=开始;
这个。结束=结束;
}
}
列表行=新列表();
专用点下降点=点。空;
私有点movePoint=Point.Empty;
私有布尔移动线=假;
公共表格1(){
初始化组件();
面板1.油漆+=面板1_油漆;
panel1.MouseDown+=panel1_MouseDown;
panel1.MouseMove+=panel1u MouseMove;
panel1.MouseUp+=panel1u MouseUp;
}
无效面板1_MouseDown(对象发送器,MouseEventArgs e){
if(e.Button==MouseButtons.Left){
下降点=e.位置;
}
}
无效面板1_MouseMove(对象发送器,MouseEventArgs e){
if(e.Button==MouseButtons.Left){
movingLine=true;
移动点=e.位置;
1.使无效();
}
}
无效面板1_MouseUp(对象发送器,MouseEventArgs e){
if(e.Button==MouseButtons.Left){
movingLine=false;
行。添加(新行(落点,e.位置));
1.使无效();
}
}
无效面板1_绘画(对象发送器,绘画事件参数e){
e、 图形。清晰(颜色。白色);
foreach(行中的行l){
e、 图形.抽绳(黑色笔,左起,左止);
}
如果(移动线路){
e、 图形.抽绳(钢笔.黑色,下降点,移动点);
}
}

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

无论何时您想要重新绘制(在代码中),都应该调用panelinvalidate
drawPanel.Invalidate()

完成鼠标移动并释放按钮后

private void drawPanel_MouseUp(object sender, MouseEventArgs e)
{
            onMouseUpFlag = true;
            drawPanel.Invalidate();
}
最后,我建议您在drawPanel_Paint中使用此代码,而不是在您的drawPanel_Paint中使用此代码 . 您应该使用EventArgs提供的图形,而不是创建新图形

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

  • 要绘制多条线,必须将每条线的信息存储在列表或其他内容中,然后在重新绘制时绘制每条线。绘制方法基本上每次都以空白开始,因此它只会按照当前设置的方式绘制最新的


  • 如果你像我一样懒惰的话,那就刷新一下。LarsTech,干得好!谢谢你的帮助!!我更新了我的答案。请尽量避免改变问题。如果您有更多问题,请随意将其作为单独的问题发布。