【问题标题】:C# WinForms flickering on any type of fast screen updateC# WinForms 在任何类型的快速屏幕更新上闪烁
【发布时间】:2019-04-16 17:03:19
【问题描述】:

我想创建一个绘图库,以便我可以可视化一些代码(类似于 java 处理)。更新绘制导致闪烁,我找不到修复它的方法。 我正在使用绘图类和 WinForms 进行绘图。 如果有其他/更好的方法可以通过使用其他东西(Unity 除外)来实现这一点,我愿意尝试。

我尝试了双缓冲,但什么也没做。无效和刷新使情况变得更糟。

编辑:它得到了修复(见 cmets)。我使用了一个找到的计时器here

以下是我的 Form 类。

Timer timer;
int i = 0;

Screen screen;
Rectangle canvas;

public Form1() {
    InitializeComponent();
    this.SetStyle(ControlStyles.UserPaint, true);
    this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
    this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
    DoubleBuffered = true;

    screen = Screen.FromControl(this);
    canvas = screen.WorkingArea;

    timer = new Timer();
    timer.Interval = 10;

    timer.Tick += new EventHandler(draw);

    timer.Enabled = true;
}

public void draw(object source, EventArgs e) {
    Graphics g = CreateGraphics();

    g.FillRectangle(new SolidBrush(Color.Black), canvas);
    g.FillRectangle(new SolidBrush(Color.White), i, 0, 100, 100);
    i++;
}

【问题讨论】:

  • 你不应该调用 CreateGraphics,在 OnPaint 方法中进行绘图,然后在计时器中使用 Invalidate()。
  • ...而且,如果您参考 Timer 的文档,您会发现它无法达到 10ms 的分辨率。并且您创建的几乎所有图形对象(例如画笔)都必须被释放,否则您的应用会泄漏
  • ...Paint() 事件通过e.Graphics 为您提供了一个图形供您绘制。
  • 它使用 OnPaint 方法和 Invalidate 在计时器中工作。 @NatPongjardenlarp 我现在找到了一个能够实现高分辨率的计时器

标签: c# winforms drawing flicker


【解决方案1】:

不要创建图形,使用传递给 OnPaint 的图形。

在计时器上,只需计算坐标并调用 Invalidate。

using System;
using System.Drawing;
using System.Windows.Forms;

namespace Flickering
{
    public partial class Form1 : Form
    {
        Timer timer;
        Rectangle rect = new Rectangle(0, 0, 100, 100);
        Size speed = new Size(3, 1);
        Size step = new Size(3, 1);

        public Form1()
        {
            InitializeComponent();

            this.SetStyle(ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);

            timer = new Timer();
            timer.Interval = 20;
            timer.Tick += new EventHandler(Tick);
            timer.Enabled = true;
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            //e.Graphics.FillRectangle(Brushes.DarkCyan, ClientRectangle);
            e.Graphics.FillRectangle(Brushes.White, rect);
        }

        public void Tick(object source, EventArgs e)
        {
            var canvas = ClientRectangle;
            step.Width = rect.Right >= canvas.Width ? -speed.Width : rect.Left < canvas.Left ? speed.Width : step.Width;
            step.Height = rect.Bottom >= canvas.Height ? -speed.Height : rect.Top < canvas.Top ? speed.Height : step.Height;
            rect.Location += step;

            Invalidate();
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-09
    • 2018-11-17
    • 2015-10-19
    • 1970-01-01
    • 2011-09-29
    • 1970-01-01
    相关资源
    最近更新 更多