如何在窗体中以平滑的形式重新绘制

时间:2014-03-05 22:46:06

标签: c# winforms panel paint paintevent

如何平滑地重新绘制面板?

我使用的计时器每300毫秒使面板(panel1.Invalidate();)无效,然后在panel1_Paint事件中我将图像添加到该面板,问题是它看起来像是跳跃和我需要尽可能快地在其上移动一个图像。

这是屏幕播放问题的链接:http://screencast.com/t/HdtIV99YN

 private void panel1_Paint(object sender, PaintEventArgs e)
            {
                PaintMapObstacles(e);
                PaintMapStartAndGoal(e);

                if (trayectoryIndex < 1000)
                {
                   MapPoint point =  GetTrayectoryPoint(0, trayectoryIndex);
                   e.Graphics.DrawImage(new Bitmap("robot.jpg"), point.X*squareSize, point.Y*squareSize, 60, 60);
                   trayectoryIndex++;
               }
            }
     private void PaintMapStartAndGoal(PaintEventArgs e)
            {
                MapPoint start = new MapPoint { X = 0, Y = 0 };
                MapPoint goal = new MapPoint { X = 7, Y = 8 };
                   // e.Graphics.DrawImage(new Bitmap("start.jpg"), start.X * squareSize, start.Y * squareSize, 60, 60);
                    e.Graphics.DrawImage(new Bitmap("goal.jpg"), goal.X * squareSize, goal.Y * squareSize, 60, 60);
                    isFirstRun = true;
            }


        private void PaintMapObstacles(PaintEventArgs e)
            {

                foreach (MapPoint mpoint in obstacles.Obstacles)
                {
                    e.Graphics.DrawImage(new Bitmap("obstacle.png"), mpoint.X * squareSize, mpoint.Y * squareSize, 60, 60);  
                }
            }

         private void PanelTimer_Tick(object sender, EventArgs e)
            {

                panel1.Invalidate();
            }

1 个答案:

答案 0 :(得分:3)

它被称为“闪烁”,一种从头开始重绘窗口时总是存在的神器。它在您的程序中尤其明显,因为您的绘图代码效率很低。你会看到窗口的背景被绘制,擦除了旧画。然后慢慢地将位图拉回到背景上。擦除步骤对眼睛是可见的,看起来像闪烁。

闪烁的一般解决方法是双缓冲,首先将窗口内容组合成位图,然后快速将位图blit到屏幕。它是Winforms的内置功能,DoubleBuffered属性将其打开。 Panel类没有默认启用双缓冲,它被设计为一个容器控件,除了绘制背景之外,它不会自行绘制。 PictureBox在您的情况下也可以正常工作,它默认启用双缓冲。或者,您可以为Panel类shown here打开双缓冲。

你确实希望最终解决你的绘图代码的问题,除了它非常慢,它可能会崩溃你的程序与OutOfMemoryException。由您使用Bitmap类的方式引起的问题,它应该在您使用它之后处理。始终对System.Drawing对象使用 using 语句。

通过仅创建一次位图,您可以更快地完成任务,表单构造函数是最佳位置。通过预先定位位图以适应网格并注意像素格式,可以快速实现 。 PixelFormat.Format32bppArgb与几乎所有现代视频适配器的帧缓冲格式直接兼容,位图可以直接复制到帧缓冲区而无需转换。比所有其他格式快十倍。转换代码is here