为什么我的表格闪烁

本文关键字:闪烁 表格 我的 为什么 | 更新日期: 2023-09-27 18:36:04

我已经实现了一个简单的多线程服务器''客户端游戏作为我大学的作业。

在客户端,除了主线程之外,还有:

1线程,负责在表格上绘制游戏场地和球员。

2线程与服务器通信,发送方向并接收位置等信息。

首先我使用了调用技术,但它不起作用,因为我在处理图形后使用了图形。 请参阅通过单独的线程在窗体上绘制

所以为了避免这种情况并使绘图线程正规化,我只是在绘图线程上每次特定时间都举起"无效"标志,并将其的实际处理留给主线程:

    public Form1()
    {
        SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
        InitializeComponent();
    }
    private void Draw()
    {
        while (true)
        {
            Thread.Sleep(200);
            Invalidate();
        }
    }
    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        if (map.hasGraph)
        {
            map.Draw(e.Graphics);
            if (this.Index != null)
                e.Graphics.FillRectangle(Brush, Rectangle);
            if (OpponentIndex != null)
                e.Graphics.FillRectangle(OpponentBrush, OpponentRectangle);
        }
    }

这里的问题是,即使我使用双缓冲,表单也会以任意方式闪烁,并且当我增加绘图线程的睡眠时间时,闪烁会减少,但我认为 200ms 已经太多了。有什么建议吗?

[编辑]

我意识到我正在从代码和属性编辑器中设置双缓冲标志,这

引起了问题(这可能是一个愚蠢的想法),但我花了半个小时用其中一个标志和两个标志测试我的代码,当我从两个地方设置双缓冲标志时提出的问题, 我的问题已经解决了,但现在我需要知道这是否可以解决它。

为什么我的表格闪烁

一定运行的时间越长,情况就越糟?

每次程序绘制时,它都会启动 draw,它有一个无限循环,它调用 paint,在另一个无限循环中调用 draw。 看来你在这里有一个循环参考。 如果我能假设 Map.Draw 是私有的 void Draw()

有一个更简单的解决方案,将所有内容绘制到位图,然后在 onPaint 事件中绘制位图。

Bitmap buffer=new Bitmap(this.Width, this.Height); //make sure to resize the bitmap during the Form.Onresize event
Form1()
{
    InitializeComponent();
    Timer timer=new Timer();
    timer.Interval= 100;
    timer.Tick+=......
    timer.Start()
}
//the Timer tick event
private void timer_tick(....
{
    if (map.hasGraph)
    {
         using (Graphics g = Graphics.FromImage(buffer))
        {
            //You might need to clear the Bitmap first, and apply a backfround color or image
            //change color to whatever you want, or don't use this line at all, I don't know
            g.Clear(Color.AliceBlue);
            if (this.Index != null)
                g.FillRectangle(Brush, Rectangle);
            if (OpponentIndex != null)
                g.FillRectangle(OpponentBrush, OpponentRectangle);
        }
     panel1.BackgroundImage=buffer;
     }
}

注意 我没有测试语法准确性。

对于执行的操作,系统的内存可能相当低。阅读更多关于它的信息。http://msdn.microsoft.com/en-us/library/system.drawing.graphics.aspx

  1. 创建一个将用于存储上次渲染场景的图像。
  2. 创建新线程将绘制到图像
  3. 创建一个计时器,将刷新图像
  4. 在计时器滴答声上将图像复制到表单