C# 中可怕的闪烁绘图

本文关键字:闪烁 绘图 | 更新日期: 2023-09-27 18:32:35

有人对如何阻止此绘图闪烁有任何建议吗?我已经尝试了每种双缓冲解决方案,停止使用.CreateGraphics,将我的所有功能都移到了各个地方,没有任何效果。

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

namespace Math
{
public partial class Form1 : Form
{
    static Random rand = new Random();
    ProblemBox[] problems = new ProblemBox[20];
    #region Types
    public enum Type
    {
        Basic, Algebric, Triginomic
    }
    public class Problem
    {
        public Type type;
        public String problem, answer;
        public Boolean isTrue;
        public Problem(Type type, String problem, String answer, Boolean isTrue)
        {
            this.type = type;
            this.problem = problem;
            this.answer = answer;
            this.isTrue = isTrue;
        }
    }

    class ProblemBox
    {
        public Rectangle rect;
        public Problem problem;
        public ProblemBox(Problem problem)
        {
            rect = new Rectangle(0, 309, 244, 30);
            this.problem = problem;
        }
        public void move()
        {
            rect.Y -= 1;
        }
        public void draw(Graphics g)
        {
            g.FillRectangle(Brushes.DarkGray, rect);
            g.DrawString(problem.problem + "=" + problem.answer, new Font("Times New Roman", 12.0f), Brushes.DarkBlue, new PointF(rect.X + 5, rect.Y + 5));
        }

    }
    #endregion

     public Problem CreateProblem() {
        char op = '+';
        int a = rand.Next(20), b = rand.Next(20), c;
        switch (rand.Next(4)) { 
            case 2:
                c = a - b;
                op = '-';
                break;
            case 3:
                c = a * b;
                op = '*';
                break;
            case 4:
                c = a / b;
                op = '/';
                break;
            default:
                c = a + b;
                op = '+';
                break;
        }
        bool isTrue = rand.Next(2) == 1;
        if (!isTrue) {
            c += 1 + (10 - rand.Next(20));
        }
        return new Problem(Type.Basic, String.Concat(a + ""+op +""+ b), String.Concat(c), isTrue);

    }

    public Form1()
    {
        InitializeComponent();
        SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
        problems[0] = new ProblemBox(CreateProblem());
    }

    private void panel1_Paint(object sender, PaintEventArgs e)//Tick
    {
            ProblemBox temp = null;
            if (problems[0].rect.Y < 279)
            {
                temp = new ProblemBox(CreateProblem());
            }
            for (int i = 0; i < 20; i++)
            {
                if (temp != null)
                {
                    ProblemBox temp2 = problems[i];
                    problems[i] = temp;
                    temp = temp2;
                }
                if (problems[i] != null)
                {
                    problems[i].move();
                    problems[i].draw(e.Graphics);
                }
            }
            Thread.Sleep(20);
            DrawingPanel.Invalidate();
}
    }
}

C# 中可怕的闪烁绘图

这不是一个好主意

 Thread.Sleep(20);
 DrawingPanel.Invalidate();

Paint方法内部。尽量避免它们,行为可能会显着改善。

正如Tigran已经说过的那样,你的问题是你没有完成重绘,这可以通过以下方法轻松解决:

        (new Thread(() =>
        {
            Thread.Sleep(20);
            this.BeginInvoke((MethodInvoker)delegate { DrawingPanel.Invalidate(); });
        })).Start();

然而,闪烁也可能是由于缓慢的重新绘制(或者更确切地说 - 不够快)而发生的。在这种情况下的解决方案,如果非常简单 - 不要直接绘制到屏幕上(使用双缓冲)。

如果您需要标准组件中的某些功能,则必须创建自己的组件并适当地调用它。将Panel用于与Panel预期无关的事情 - 是不好的。

这是一个很好的开端:

    [System.ComponentModel.DesignerCategory("Code")]
    public class MyControl : PictureBox
    {
            public MyControl() 
            {
                SetStyle(ControlStyles.UserPaint | ControlStyles.ResizeRedraw | ControlStyles.DoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
                // ...
            }
    }