我有一个我已经子类化并且设置为DoubleBufferedtrue 的面板,我经常需要刷新绘图但是它闪烁并且不知道为什么.
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();
}
Run Code Online (Sandbox Code Playgroud)
因此,在每次"计算"之后并向我想象中的网格添加了一些东西,我需要更新面板以在我的网格上显示这个新项目.我已经尝试在displayGrid()功能之前使面板无效,但它似乎导致更多的闪烁.
该heartbeat()函数当前正在一个单独的线程上调用.
这是我的新Panel课程.
public class Display : Panel
{
public Display()
{
this.DoubleBuffered = true;
}
}
Run Code Online (Sandbox Code Playgroud)
Han*_*ant 10
Graphics g = drawPanel.CreateGraphics();
Run Code Online (Sandbox Code Playgroud)
使用CreateGraphics()并启用双缓冲是最糟糕的组合.CreateGraphics()为您提供直接绘制到屏幕的Graphics对象.Double-buffering设置一个Graphics对象,该对象绘制到一个位图,即双缓冲中使用的缓冲区.然后在绘制周期结束时将位图渲染到屏幕.
所以在你的代码中发生的是你直接绘制屏幕,你几乎看不到的东西,但是如果它足够慢的话可见.然后就在那之后,你从未画过的缓冲区会被绘制掉.这抹去了你之前画的东西.净效果是大量闪烁,您的油漆输出仅可见几毫秒.
使用CreateGraphics()是错误的.您总是希望通过从Paint事件获得的e.Graphics对象进行渲染,以便渲染到缓冲区.将Graphics对象传递给drawMonomers()方法.从而:
public void drawMonomers(Graphics g, Point location, string state) {
// Etc...
}
private void Display1_Paint(object sender, PaintEventArgs e) {
//...
drawMonomers(e.Graphics, loc, state);
}
Run Code Online (Sandbox Code Playgroud)
通常,CreateGraphics()的用处非常有限.当你想直接绘制到屏幕上时,你只能使用它,你可以买得起你想要消失的任何东西.这通常仅适用于具有不断运行的渲染循环的程序,以高速率生成新输出,例如每秒20帧以上.就像一个视频游戏.