C# 如何在窗口窗体中重新绘制光滑的面板

C# 如何在窗口窗体中重新绘制光滑的面板,c#,winforms,panel,paint,paintevent,C#,Winforms,Panel,Paint,Paintevent,我怎样才能将面板重新涂成光滑的颜色 我使用的计时器每300ms使面板失效(panel1.Invalidate();),然后在panel1_-Paint事件中,我将图像添加到该面板中,问题是它看起来像是在跳跃,我需要尽可能快地移动其中一个图像 这是屏幕播放问题的链接:http://screencast.com/t/HdtIV99YN private void panel1_Paint(object sender, PaintEventArgs e) {

我怎样才能将面板重新涂成光滑的颜色

我使用的计时器每300ms使面板失效(
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();
            }
private void panel 1_Paint(对象发送器,PaintEventArgs e)
{
障碍(e);
绘制地图开始和目标(e);
if(trayectoryIndex<1000)
{
MapPoint point=GetTrayectoryPoint(0,trayectoryIndex);
e、 Graphics.DrawImage(新位图(“robot.jpg”),point.X*squareSize,point.Y*squareSize,60,60);
trayectoryIndex++;
}
}
私有void PaintMapStartAndGoal(PaintEventArgs e)
{
MapPoint start=newmappoint{X=0,Y=0};
地图点目标=新地图点{X=7,Y=8};
//e.Graphics.DrawImage(新位图(“start.jpg”)、start.X*squareSize、start.Y*squareSize、60、60);
e、 Graphics.DrawImage(新位图(“goal.jpg”)、goal.X*squareSize、goal.Y*squareSize、60、60);
isFirstRun=true;
}
私有void paintmaps障碍(PaintEventArgs e)
{
foreach(障碍物中的映射点mpoint.barriends)
{
e、 Graphics.DrawImage(新位图(“barrier.png”)、mpoint.X*squareSize、mpoint.Y*squareSize、60、60);
}
}
private void PanelTimer_Tick(对象发送方,事件参数e)
{
1.使无效();
}
它被称为“闪烁”,当你从头开始重新绘制一个窗口时,它总是存在。这在程序中尤其明显,因为绘制代码效率太低。你可以看到窗户的背景被画出来,抹去了旧画。然后慢慢地将位图绘制回背景。擦除步骤肉眼可见,看起来像闪烁

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

您确实希望最终解决绘制代码的问题,除了速度非常慢之外,它还可能导致程序崩溃,并出现OutOfMemoryException。由于使用位图类的方式而导致的问题,应在使用后处理。始终对System.Drawing对象使用using语句


只需创建一次位图,就可以大大加快速度,表单构造函数是最好的地方。通过调整位图的大小以适应网格,并注意像素格式,您可以让它变得非常快速。PixelFormat.Format32bppPArgb与几乎任何现代视频适配器的帧缓冲区格式直接兼容,位图可以直接复制到帧缓冲区而无需转换。比所有其他格式快十倍。转换代码。

老兄,说真的,winforms不适合玩游戏(在2014年,我想不出任何其他东西)。如果您需要游戏框架,请使用XNA或MonoGame。否则,对于简单的棋盘类2D游戏,您可以使用WPF。@HighCore您完全正确。然而,这个项目的重点不是模拟。我正在用A*和不同的强化学习方法来做人工智能,我不想花太多时间去做结果的可视化。我从过去就知道一些winfomrs。如果你
不想花太多时间做可视化
,你应该真正使用相关技术。强迫一项不受欢迎的技术去做它确实不适合做的事情会让你损失大量的时间。更不用说太多的代码了,winforms方法本身已经比使用适当的数据绑定等方法麻烦得多。