Question

How can I repaint a panel in smooth?

I am using a timer that is invalidating the panel(panel1.Invalidate();) every 300ms, and then with the panel1_Paint event I am adding images to that panel the issue is that it looks like is jumping and I need to be moving one image on it as fast as I can.

This is a link of the screen-cast issue: 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();
            }
Was it helpful?

Solution

It is called "flicker", an artifact that's always around when you repaint a window from scratch. It is especially noticeable in your program because your painting code is so inefficient. You see the window's background getting drawn, erasing the old painting. Then slowly getting the bitmaps drawn back onto the background. The erasure step is visible to the eye and looks like flicker.

The general cure for flicker is double-buffering, composing the window content into a bitmap first, then quickly blitting the bitmap to the screen. It is a built-in feature for Winforms, the DoubleBuffered property turns it on. Double-buffering is not enabled by default for the Panel class, it was designed to be a container control that doesn't do painting on its own beyond drawing the background. A PictureBox will work just as well in your case, it has double-buffering enabled by default. Or you can turn on double-buffering for the Panel class, shown here.

You do want to eventually address the problems with your painting code, beyond it being very slow, it can crash your program with an OutOfMemoryException. A problem caused by the way you use the Bitmap class, it should be disposed after you used it. Always use the using statement for System.Drawing objects.

You'll make it a lot faster by creating the bitmaps just once, the form constructor is the best place. You make it really fast by prescaling the bitmaps to fit the grid and paying attention to the pixel format. PixelFormat.Format32bppPArgb is directly compatible with the frame buffer format of almost any modern video adapter, the bitmap can be directly copied into the frame buffer without conversion. Ten times faster than all the other formats. Conversion code is here.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top