C#图形闪烁

标签 c# .net winforms system.drawing

我正在开发一种绘图程序,但在绘制橡皮筋线时移动鼠标光标时出现闪烁问题。我希望你能帮我消除那条闪烁的线,这是代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace GraphicsTest
{
    public partial class Form1 : Form
    {
        int xFirst, yFirst;
        Bitmap bm = new Bitmap(1000, 1000);
        Graphics bmG;
        Graphics xG;
        Pen pen = new Pen(Color.Black, 1);
        bool draw = false;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            bmG = Graphics.FromImage(bm);
            xG = this.CreateGraphics();
            bmG.Clear(Color.White);
        }

        private void Form1_MouseDown(object sender, MouseEventArgs e)
        {
            xFirst = e.X;
            yFirst = e.Y;
            draw = true;
        }

        private void Form1_MouseUp(object sender, MouseEventArgs e)
        {
            bmG.DrawLine(pen, xFirst, yFirst, e.X, e.Y);
            draw = false;
            xG.DrawImage(bm, 0, 0);
        }

        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            if (draw)
            {
                xG.DrawImage(bm, 0, 0);
                xG.DrawLine(pen, xFirst, yFirst, e.X, e.Y);
            }
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            xG.DrawImage(bm, 0, 0);
        }
    }
}

最佳答案

首先不要使用 CreateGraphics() 除非绝对必要。将事件处理程序绑定(bind)到 OnPaint 并在您想要刷新表面时调用 Invalidate()

如果您不希望它闪烁,则需要对您的绘图表面进行双重缓冲。最简单的方法是将表单的 DoubleBuffered 属性设置为 True。

如果您打算扩展它以对 PictureBox 控件进行绘图,我强烈推荐您使用它。 PictureBox 默认是双缓冲的,允许您更简单地控制绘图区域。

在代码中:

public partial class Form1 : Form
    {
    int xFirst, yFirst;
    Bitmap bm = new Bitmap(1000, 1000);
    Graphics bmG;
    Pen pen = new Pen(Color.Black, 1);
    bool draw = false;

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        bmG = Graphics.FromImage(bm);
        bmG.Clear(Color.White);
    }

    private void Form1_MouseDown(object sender, MouseEventArgs e)
    {
        xFirst = e.X;
        yFirst = e.Y;
        draw = true;
    }

    private void Form1_MouseUp(object sender, MouseEventArgs e)
    {
        bmG.DrawLine(pen, xFirst, yFirst, e.X, e.Y);
        draw = false;
        Invalidate();
    }

    private void Form1_MouseMove(object sender, MouseEventArgs e)
    {
        if (draw)
        {
            Invalidate();
        }
    }

    private void Form1_Paint(object sender, PaintEventArgs e)
    {
        if (draw) {
            e.Graphics.DrawImage(bm, 0, 0);
            e.Graphics.DrawLine(pen, xFirst, yFirst, e.X, e.Y);
        } else {
            e.Graphics.DrawImage(bm, 0, 0);
        }
    }
}

编辑:

另一个问题,您正在创建一个私有(private) Pen 成员。笔(和画笔,以及许多 GDI+ 对象)表示需要处理的非托管对象的句柄,否则您的程序将泄漏。要么将它们包装在 using 语句中(首选且异常安全的方式),要么在表单的 Dispose 方法中显式处理它们。

或者,在 System.Drawing 中,您可以访问一些不需要(也不应该)处理的预建钢笔和画笔。像这样使用它们:

    private void Form1_Paint(object sender, PaintEventArgs e)
    {
        if (draw) {
            e.Graphics.DrawImage(bm, 0, 0);
            e.Graphics.DrawLine(Pens.Black, xFirst, yFirst, e.X, e.Y);
        } else {
            e.Graphics.DrawImage(bm, 0, 0);
        }
    }

关于C#图形闪烁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2608909/

相关文章:

c# - 异步匿名无参数方法作为方法参数

c# - 默认构造函数创建的 `Dictionary`是否使用哈希码?

c# - 为什么 InvokeRequired 优于 WindowsFormsSynchronizationContext?

C# Winforms 动态菜单条目

winforms - 为什么在我在文本框中输入 "only"一个字符后,我的文本框 TextChanged 事件会被触发?

c# - 框架类中记录的 protected 属性有什么用?

c# - 如果我设置断点,我的 JavaScript 只会调用我的 Web 服务。你知道为什么吗?

c# - 我可以使用计时器每 x 毫秒更新一次标签吗

c# - 阻塞任务?

c# - .NET/C#中swagger json规范到静态html文件的转换