0

有人对如何阻止此绘图闪烁有任何建议吗?我已经尝试过每种双缓冲解决方案,停止使用 .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();
}
    }
}
4

2 回答 2

3

这不是一个好主意

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

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

于 2013-09-24T06:42:39.963 回答
0

正如 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);
                // ...
            }
    }
于 2013-09-24T07:06:58.660 回答