如何重画修复面板闪烁? [英] How to fix panel flickering when redrawing?

查看:132
本文介绍了如何重画修复面板闪烁?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有我的子类并设置了面板 DoubleBuffered 真的,我需要不断刷新图纸,但它闪烁,不知道为什么。

 私人委托无效MyDelegate(); 

公共无效的心跳()
{
,而(真)
{
如果(map.processNubots(规则))
$ { b $ b如果(this.InvokeRequired)
{
this.Invoke((MyDelegate)代表
{
//drawPanel.SuspendLayout();
drawPanel.Refresh ();
displayGrid();
//drawPanel.ResumeLayout();
});
}
的Thread.Sleep(500);
}
,否则
{
中断;
}
}
}

公共无效displayGrid()
{
INT I = 0;
的foreach(在地图的DictionaryEntry对)
{
单体电流=(单体)pair.Value;
drawMonomers(current.getLocation(),current.getState());
I ++;
}
}

公共无效drawMonomers(点位置,串状态)
{
...

SolidBrush SB =新SolidBrush(mycolor);
SolidBrush SBT =新SolidBrush(Color.Black);
图形G = drawPanel.CreateGraphics();
字体文本=新的字体(宋体,规​​模/ 2);
喷喷=新朋(Color.Black,1);
pen.Alignment = PenAlignment.Inset;
g.FillEllipse(某人,偏移+((location.Y *刻度)/ 2)+(location.X *刻度),偏移+(-location.Y *刻度),刻度,刻度);
g.DrawEllipse(笔,偏移+((location.Y *刻度)/ 2)+(location.X *刻度),偏移+(-location.Y *刻度),刻度,刻度);
g.DrawString(状态,文本,SBT,(偏移+((location.Y *刻度)/ 2)+(location.X *刻度))+缩放/ 6,(偏移+(-location.Y *等级))+规模/ 6);

sb.Dispose();
sbt.Dispose();
pen.Dispose();
}



所以经过每一个计算,并打听到我想象的网格,我需要更新的面板上显示网格我这个新项目。我曾尝试 displayGrid()函数前右侧的面板中无效,但它似乎导致更多的闪烁。<​​/ p>

心跳()函数目前被称为一个单独的线程。



下面是我的新<$ C $ 。C>面板类

 公共类显示:面板
{
公共显示()
{
this.DoubleBuffered = TRUE;

}
}


解决方案

 图形G = drawPanel.CreateGraphics(); 



使用的createGraphics()的的开启双缓冲是最坏的可能组合。的createGraphics()为您提供了直接绘制到屏幕上一个图形对象。双缓冲设置绘制成位图,双缓冲使用的缓冲区的图形对象。然后呈现位在油漆周期结束的屏幕。



那么,在你的代码的情况是,你直接绘制屏幕,​​有些东西你可以勉强看到,但可见,如果它是够慢。再经过正确的,你从来没有吸引到被涂缓冲区。其中打掉你以前画的画。净效应是的闪烁与涂料产量仅为毫秒极少数可见。



使用的createGraphics()是错误的。您的总是的要渲染通过e.Graphics对象,您从Paint事件得到,所以你渲染到缓冲区。传递Graphics对象的drawMonomers()方法。因此:

 公共无效drawMonomers(图形克,点位置,串州){
//等等...
}

私人无效Display1_Paint(对象发件人,PaintEventArgs的E){
// ...
drawMonomers(e.Graphics,禄,状态);
}

在一般情况下,的createGraphics()拥有的非常的有限用处。你只曾经使用它时,你的希望的直接绘制到屏幕上,你可以买得起任何你画消失。这通常是只有在那种方案的具有该持续运行,以高速率像每秒20+帧产生新的输出呈现循环是有用的。像视频游戏。


I have a panel that I've subclassed to and have set DoubleBuffered true, I constantly need to refresh the drawing but it flickers and have no idea why.

private delegate void MyDelegate();

public void heartBeat()
    {
        while (true)
        {
            if (map.processNubots(rules))
            {
                if (this.InvokeRequired)
                {
                    this.Invoke((MyDelegate)delegate
                    {
                        //drawPanel.SuspendLayout();
                        drawPanel.Refresh();
                        displayGrid();
                        //drawPanel.ResumeLayout();
                    });
                }
                Thread.Sleep(500);
            }
            else
            {
                break;
            }
        }
    }

    public void displayGrid()
    {
        int i = 0;
        foreach (DictionaryEntry pair in map)
        {
            Monomer current = (Monomer)pair.Value;
            drawMonomers(current.getLocation(), current.getState());
            i++;
        }
    }

    public void drawMonomers(Point location, string state)
    {
        ...

        SolidBrush sb = new SolidBrush(mycolor);
        SolidBrush sbt = new SolidBrush(Color.Black);
        Graphics g = drawPanel.CreateGraphics();
        Font text = new Font("Arial", scale / 2);
        Pen pen = new Pen(Color.Black, 1);
        pen.Alignment = PenAlignment.Inset;
        g.FillEllipse(sb, offSet + ((location.Y * scale) / 2) + (location.X * scale), offSet + (-location.Y * scale), scale, scale);
        g.DrawEllipse(pen, offSet + ((location.Y * scale) / 2) + (location.X * scale), offSet + (-location.Y * scale), scale, scale);
        g.DrawString(state, text, sbt, (offSet + ((location.Y * scale) / 2) + (location.X * scale)) + scale / 6, (offSet + (-location.Y * scale)) + scale / 6);

        sb.Dispose();
        sbt.Dispose();
        pen.Dispose();
    }

So after every "computation" and have added something to my imaginary grid, I need to update the panel to show this new item on my grid. I have tried invalidating the panel right before the displayGrid() function but it seems to cause even more flickering.

The heartbeat() function is currently being called on a separate thread.

Here is my new Panel class.

public class Display : Panel
{
    public Display()
    {
        this.DoubleBuffered = true;

    }
}

解决方案

    Graphics g = drawPanel.CreateGraphics();

Using CreateGraphics() and turning on double-buffering is the worst possible combination. CreateGraphics() gives you a Graphics object that draws directly to the screen. Double-buffering sets up a Graphics object that draws to a bitmap, the buffer used in double-buffering. Then renders the bitmap to the screen at the end of the paint cycle.

So what happens in your code is that you draw the screen directly, something you can barely see but visible if it is slow enough. Then right after that the buffer that you never draw into gets painted. Which wipes out what you drew before. The net effect is heavy flicker with your paint output visible for only a handful of milliseconds.

Using CreateGraphics() was the mistake. You always want to render through the e.Graphics object that you get from the Paint event so you'll render to the buffer. Pass that Graphics object to your drawMonomers() method. Thus:

public void drawMonomers(Graphics g, Point location, string state) {
   // Etc...
}

private void Display1_Paint(object sender, PaintEventArgs e) {
   //...
   drawMonomers(e.Graphics, loc, state);
}

In general, CreateGraphics() has very limited usefulness. You only ever use it when you want to draw to the screen directly and you can afford for whatever you draw to disappear. That is typically only useful in the kind of program that has a render loop that constantly runs, producing new output at a high rate like 20+ frames per second. Like a video game.

这篇关于如何重画修复面板闪烁?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆