how to stop flickering C# winforms

前端 未结 16 2116
故里飘歌
故里飘歌 2020-11-28 04:16

I have a program that is essentially like a paint application. However, my program has some flickering issues. I have the following line in my code (which should get rid of

相关标签:
16条回答
  • 2020-11-28 04:36

    just do this.Refresh() when shown the form.

    0 讨论(0)
  • 2020-11-28 04:37

    In this condition you have to enable double buffer . Open current form and go to form properties and apply double buffer true; or you can also write this code .

    this.DoubleBuffered = true;     
    

    In form load.

    0 讨论(0)
  • 2020-11-28 04:39

    Double buffering is not going to be of much help here I'm afraid. I ran into this a while ago and ended up adding a separate panel in a rather clumsy way but it worked for my application.

    Make the original panel that you have ( panelArea ) a transparent area, and put it on top of a 2nd panel, which you call panelDraw for example. Make sure to have panelArea in front. I whipped this up and it got rid of the flickering, but left the shape that was being drawn smeared out so it's not a full solution either.

    A transparent panel can be made by overriding some paint actions from the original panel:

    public class ClearPanel : Panel
    {
        public ClearPanel(){}
    
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams createParams = base.CreateParams;
                createParams.ExStyle |= 0x00000020;
                return createParams;
            }
        }
    
        protected override void OnPaintBackground(PaintEventArgs e){}
    }
    

    The idea is to handle drawing the temporary shape during the MouseMove event of the 'panelArea' and ONLY repaint the 'panelDraw' on the MouseUp Event.

    // Use the panelDraw paint event to draw shapes that are done
    void panelDraw_Paint(object sender, PaintEventArgs e)
    {
        Graphics g = panelDraw.CreateGraphics();
    
        foreach (Rectangle shape in listOfShapes)
        {
            shape.Draw(g);
        }
    }
    
    // Use the panelArea_paint event to update the new shape-dragging...
    private void panelArea_Paint(object sender, PaintEventArgs e)
    {
        Graphics g = panelArea.CreateGraphics();
    
        if (drawSETPaint == true)
        {
            Pen p = new Pen(Color.Blue);
            p.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
    
            if (IsShapeRectangle == true)
            {
                g.DrawRectangle(p, rect);
            }
            else if (IsShapeCircle == true)
            {
                g.DrawEllipse(p, rect);
            }
            else if (IsShapeLine == true)
            {
                g.DrawLine(p, startPoint, endPoint);
            }
        }
    }
    
    private void panelArea_MouseUp(object sender, MouseEventArgs e)
    {
    
        endPoint.X = e.X;
        endPoint.Y = e.Y;
    
        drawSETPaint = false;
    
        if (rect.Width > 0 && rect.Height > 0)
        {
            if (IsShapeRectangle == true)
            {
                listOfShapes.Add(new TheRectangles(rect, currentColor, currentBoarderColor, brushThickness));
            }
            else if (IsShapeCircle == true)
            {
                listOfShapes.Add(new TheCircles(rect, currentColor, currentBoarderColor, brushThickness));
            }
            else if (IsShapeLine == true)
            {
                listOfShapes.Add(new TheLines(startPoint, endPoint, currentColor, currentBoarderColor, brushThickness));
            }
    
            panelArea.Invalidate();
        }
    
        panelDraw.Invalidate();
    }
    
    0 讨论(0)
  • 2020-11-28 04:42

    Drawing onto a Label instead of a Panel, solved the problem for me.

    No need to use DoubleBuffering or anything either.

    You can remove the text from the label, set AutoSize to false, then Dock it or set the Size and use it as for the Panel.

    Best wishes,

    0 讨论(0)
  • 2020-11-28 04:45

    I have had the same problem. I was never able to 100% rid myself of the flicker (see point 2), but I used this

    protected override void OnPaint(PaintEventArgs e) {}
    

    as well as

    this.DoubleBuffered = true;
    

    The main issue for flickering is making sure you

    1. paint things it the right order!
    2. make sure your draw function is < about 1/60th of a second

    winforms invokes the OnPaint method each time the form needs to be redrawn. There are many ways it can be devalidated, including moving a mouse cursor over the form can sometimes invoke a redraw event.

    And important note about OnPaint, is you don't start from scratch each time, you instead start from where you were, if you flood fill the background color, you are likely going to get flickering.

    Finally your gfx object. Inside OnPaint you will need to recreate the graphics object, but ONLY if the screen size has changed. recreating the object is very expensive, and it needs to be disposed before it is recreated (garbage collection doesn't 100% handle it correctly or so says documentation). I created a class variable

    protected Graphics gfx = null;
    

    and then used it locally in OnPaint like so, but this was because I needed to use the gfx object in other locations in my class. Otherwise DO NOT DO THIS. If you are only painting in OnPaint, then please use e.Graphics!!

    // clean up old graphics object
    gfx.Dispose();
    
    // recreate graphics object (dont use e.Graphics, because we need to use it 
    // in other functions)
    gfx = this.CreateGraphics();
    

    Hope this helps.

    0 讨论(0)
  • 2020-11-28 04:50

    For a "cleaner solution" and in order to keep using the base Panel, you could simply use Reflection to implement the double buffering, by adding this code to the form that holds the panels in which you want to draw in

        typeof(Panel).InvokeMember("DoubleBuffered", 
        BindingFlags.SetProperty | BindingFlags.Instance | BindingFlags.NonPublic, 
        null, DrawingPanel, new object[] { true });
    

    Where "DrawingPanel" is the name of the panel that you want to do the double buffering.

    I know quite a lot of time has passed since the question was asked, but this might help somebody in the future.

    0 讨论(0)
提交回复
热议问题