C # WinForms мерцание на любом типе быстрого обновления экрана - PullRequest
0 голосов
/ 13 апреля 2019

Я хочу создать библиотеку чертежей, чтобы я мог визуализировать некоторый код (что-то вроде обработки для Java). Обновление нарисованного вызывает мерцание, и я не могу найти способ исправить это. Я рисую с помощью класса Drawing и WinForms. Если есть другой / лучший способ реализовать это с помощью чего-то другого (кроме Unity), я готов попробовать это.

Я попробовал это с двойной буферизацией, которая ничего не сделала. Invalidate и Refresh сделали его намного хуже.

РЕДАКТИРОВАТЬ: Это исправлено (см. Комментарии). Я использовал найденный таймер здесь

Ниже приведен мой класс Форма.

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

1 Ответ

2 голосов
/ 15 апреля 2019

Не создавайте графику, используйте ту, которая была передана в 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();
        }
    }
}
...