【问题标题】:Drawing a line without duplicating in Winforms在Winforms中绘制一条不重复的线
【发布时间】:2019-08-02 17:01:18
【问题描述】:

您好,我想使用鼠标事件在 winforms 中的图片框中绘制一条直线。我使用鼠标按下、鼠标移动和鼠标向上事件来绘制一条线。但是,当我移动鼠标时,还会绘制其他几条线。

如果有人可以提供有关如何解决此问题的指南,我将不胜感激。

我还附上了我的代码的 sn-ps 供您参考。提前谢谢!

    private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
    {

        mousepress = true;
        x1 = e.Location.X;
        y1= e.Location.Y;
        if (counter>0)
        {
            this.Invalidate();
            pictureBox1.Refresh();
        }
    }

    private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
    {

        Graphics g = pictureBox1.CreateGraphics();
        Pen newpen = new Pen(Color.Blue, 1);



        if (mousepress)
        {
            g.DrawLine(newpen, x1, y1, e.Location.X, e.Location.Y);
            x2 = e.Location.X;
            y2 = e.Location.Y;
            angle = GetAngle(x1, y1, x2, y2);
        }
        Invalidate();


    }

  private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
    {
        mousepress = false;
        double tempX=e.Location.X, tempY=e.Location.Y;

        {
            textBox_coordinates.Text = "Index: " + i + Environment.NewLine + "X: " + x2
         + Environment.NewLine + "Y: " + y2 + Environment.NewLine + "Angle: " + angle;
            i++;

        }

        counter++;
    }

【问题讨论】:

标签: c# winforms


【解决方案1】:

在 MouseMove 事件中,您还必须刷新 PictureBox 以清除您在先前调用中绘制的线条。并且永远不要忘记在分配非托管图形资源后对其进行处置,除非您想要一个内存漏洞。

private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
    // vvv take care of automatic disposal 
    using (Graphics g = pictureBox1.CreateGraphics())
    using (Pen newpen = new Pen(Color.Blue, 1))
    {
        if (mousepress)
        {
            pictureBox1.Refresh(); // <-- get rid of the previous lines

            g.DrawLine(newpen, x1, y1, e.Location.X, e.Location.Y);
            x2 = e.Location.X;
            y2 = e.Location.Y;
            angle = GetAngle(x1, y1, x2, y2);
        }
        // Invalidate(); // check if necessary!
    }
}

编辑:获得你想要的东西的另一种方法是拦截绘画事件并在那里画线(在继承的 PictureBox 绘图之后)。我想大多数人会认为这是一个更干净的解决方案,因为这正是绘制事件的目的。但如果你只是想快速完成狭窄的任务,上面建议的解决方案就足够了。

【讨论】:

  • 你测试过这个吗?我想知道 Invalidate 是否有任何意义/差异?
  • 是的,我做到了,它确实解决了问题(我也观察到了)。我现在已经丢弃了代码,但如果你已经调用了 PictureBox.Refresh,我猜对 Invalidate 的调用是多余的。
  • @TaW:啊,现在我明白了你的反对意见,对 Invalidate 的调用应该会导致再次重绘,甚至删除最新的用户绘制的线条。嗯,恐怕我不知道为什么这不会发生......
  • 它只适用于表单,而不适用于它的子控件。为此,您将编写 pictureBox1.Invalidate()。不! ;-)(所以,请从答案中删除它!)
  • 大家好,感谢您的帮助!我试过你的建议,但还是不行:(
【解决方案2】:

类似的...

public partial class Form1 : Form
{
    bool mousepressed;
    int x1=0, y1=0,x2=0,y2=0;
    Pen newPen = new Pen(Color.Blue, 2);
    public Form1()
    {
        InitializeComponent();
    }

    private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
    {
        mousepressed = true;
        x1 = e.X;
        y1 = e.Y;
    }

    private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
    {
        if (mousepressed)
        {
            x2 = e.X;
            y2 = e.Y;
            pictureBox1.Refresh();
        }            
    }
    private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.DrawLine(newPen, x1, y1, x2, y2);
    }

    private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
    {
        mousepressed = false;
    }
}

【讨论】:

    猜你喜欢
    • 2011-03-18
    • 2013-06-13
    • 2020-03-31
    • 1970-01-01
    • 2018-11-26
    • 1970-01-01
    • 1970-01-01
    • 2011-05-02
    • 1970-01-01
    相关资源
    最近更新 更多