0

I've looked everywhere for double buffering of panels, but it all uses too confusing terms form me. I am graphing biorhythms and want to have a move function to slowly shift forward the biorhythms. However, it flashes alot so I need to figure out how to stop that. I tried to thread it, but to no avail, as threading still caused the flickering.

The following goes inside a timer: You can skip to the bottom to see where it draws the graphics. Basically, it refreshes, calculates, and plots the points.

  Panel p = panel1;
        p.Refresh();
        double physical = Math.Sin(2 * Math.PI * t / 23) * 100;
        double emotional = Math.Sin(2 * Math.PI * t / 28) * 100;
        double intellectual = Math.Sin(2 * Math.PI * t / 33) * 100;
        double physicalint = int.Parse(Math.Round(physical).ToString());
        double emotionalint = int.Parse(Math.Round(emotional).ToString());
        double intellectualint = int.Parse(Math.Round(intellectual).ToString());

        Console.WriteLine(physical + " Physical, " + emotional + " Emotional, " + intellectual + " Intellectual.");
        Console.WriteLine(physicalint + " Physical, " + emotionalint + " Emotional, " + intellectualint + " Intellectual.");

        int midpt = p.Width / 2;
        double Mastery = (physicalint + intellectualint) / 2;
        double Passion = (physicalint + emotionalint) / 2;
        double Wisdom = (emotionalint + intellectualint) / 2;
        int mastery = int.Parse(Math.Round(Mastery).ToString());
         int passion = int.Parse(Math.Round(Passion).ToString());
         int wisdom = int.Parse(Math.Round(Wisdom).ToString());
        Results.Text = "Primary Biorhythms\nPhysical: " + physicalint.ToString() + "\nEmotional: " + emotionalint.ToString() + "\nIntellectual: " + intellectualint.ToString();
        Results.Text += "\nSecondary Biorhythms\nWisdom: " + wisdom.ToString() + "\nPassion: " + passion.ToString() + "\nMastery: " + mastery.ToString();


        int eanum = int.Parse(Spread.Text);

        if (mode == 0)
        {


            for (int i = -eanum; i <= eanum; i++)
            {
                double actualheightphy = p.Height / 2;
                double physical2 = Math.Sin(2 * Math.PI * (t + i) / 23) * 100;
                double emotional2 = Math.Sin(2 * Math.PI * (t + i) / 28) * 100;
                double intellectual2 = Math.Sin(2 * Math.PI * (t + i) / 33) * 100;
                if (physical2 < 0) { physical2 = physical2 * 1.45; }
                if (physical2 > 0) { physical2 = physical2 * 1.5; }
                if (emotional2 < 0) { emotional2 = emotional2 * 1.45; }
                if (emotional2 > 0) { emotional2 = emotional2 * 1.5; }
                if (intellectual2 < 0) { intellectual2 = intellectual2 * 1.45; }
                if (intellectual2 > 0) { intellectual2 = intellectual2 * 1.5; }
                actualheightphy -= physical2;
                double actualheightemo = p.Height / 2;
                double actualheightint = p.Height / 2;
                actualheightemo -= emotional2;
                actualheightint -= intellectual2;
                int distancebetween = p.Width / eanum;

                p.CreateGraphics().FillEllipse(Brushes.Red, i * distancebetween + midpt - 5, int.Parse(Math.Round(actualheightphy).ToString()) - 5, 10, 10);
                p.CreateGraphics().FillEllipse(Brushes.Blue, i * distancebetween + midpt - 5, int.Parse(Math.Round(actualheightemo).ToString()) - 5, 10, 10);
                p.CreateGraphics().FillEllipse(Brushes.Green, i * distancebetween + midpt - 5, int.Parse(Math.Round(actualheightint).ToString()) - 5, 10, 10);
                if (i % 7 == 0)
                {
                    p.CreateGraphics().DrawString(i.ToString(), new Font(FontFamily.GenericSansSerif, 8, FontStyle.Regular), Brushes.White, new RectangleF(i * distancebetween + midpt - 5, p.Height - 12, 30, 30));
                }
                if (eanum == 7)
                {
                    p.CreateGraphics().DrawString(i.ToString(), new Font(FontFamily.GenericSansSerif, 8, FontStyle.Regular), Brushes.White, new RectangleF(i * distancebetween + midpt - 5, p.Height - 12, 30, 30));

                }
            }
            p.CreateGraphics().DrawLine(Pens.White, 0, (p.Height) / 2, p.Width, (p.Height) / 2);
            p.CreateGraphics().DrawLine(Pens.White, p.Width / 2, 0, p.Width / 2, p.Height);

            this.CreateGraphics().DrawString("100", new Font(FontFamily.GenericSansSerif, 10, FontStyle.Regular), Brushes.Black, new RectangleF(p.Width / 2 + p.Left - 15, -1, 100, 100));
            this.CreateGraphics().DrawString("-100", new Font(FontFamily.GenericSansSerif, 10, FontStyle.Regular), Brushes.Black, new RectangleF(p.Width / 2 + p.Left - 15, p.Height + p.Top + 1, 100, 100));
        }
  • Did you look at this: http://stackoverflow.com/questions/818415/how-do-i-double-buffer-a-panel-in-c?rq=1 – Noctis Oct 12 '13 at 23:48

1 Answers1

0

A possible cause may be that, by nature of the CreateGraphics method, you're creating a new Graphics object each time you draw something. It'll then be luck as to which one gets drawn, so I imagine it must flicker significantly.

So, grab the return value of p.CreateGraphics() and reuse that for all your draws, rather than calling it multiple times; e.g. :

p.CreateGraphics().FillEllipse(...);
p.CreateGraphics().FillEllipse(...);
p.CreateGraphics().FillEllipse(...);

Should be:

Graphics graphics=p.CreateGraphics();
...
graphics.FillEllipse(...);
graphics.FillEllipse(...);
graphics.FillEllipse(...);
Luke Briggs
  • 3,745
  • 1
  • 14
  • 26
  • This is slightly better, but it is still flickering. – user2635167 Oct 13 '13 at 00:18
  • Have you swapped out all CreateGraphics() calls? You've got more than just those 3 in there - that may be why :) – Luke Briggs Oct 13 '13 at 00:21
  • yes, they're all swapped out. The only other createGraphics() are on the form, and they are just numbers being drawn. In other words, they wont have an effect. Should I still be refreshing the panel? – user2635167 Oct 13 '13 at 00:26
  • You shouldn't need to, but depending on everything else going on in your program it may start 'smearing' (you'll see what I mean if it happens!) in which case you'll require a Clear. – Luke Briggs Oct 13 '13 at 00:29
  • It certainly does need to refresh, as it certainly does smear! any other ideas? – user2635167 Oct 13 '13 at 00:31
  • Is it at least not flickering? It may still flicker depending on the style settings of your control but only when you resize the window. A clear would be required there - that is basically like painting over everything it drew in the last frame to start over, and you'd do that with e.g. graphics.Clear(Color.White); as soon as your ready to start drawing again. – Luke Briggs Oct 13 '13 at 00:35
  • No, it's flickering. and I plan on having it be one size through the whole thing. But it smears when I remove the refreshes. Why is that? I set it to be double buffered. – user2635167 Oct 13 '13 at 00:38
  • Oh! I see the issue. I can't seem to set panel1 to .doublebuffered = true. It isn't showing up as an option, and is an error when I type it in. – user2635167 Oct 13 '13 at 00:40
  • Yep that's right - it's read only; use panel1.SetStyle(ControlStyles.DoubleBuffered,true); instead in your panel1 setup code (not the timers method). Smearing gets caused by the things drawn on the previous frame still being visible, and the new frame getting drawn straight over the top. – Luke Briggs Oct 13 '13 at 00:43
  • There is no set up code cause I dragged it from the toolbox. There is an error in the onload if it's put there. where else should it go? – user2635167 Oct 13 '13 at 00:49
  • Hmm I don't personally use VS but I believe you would place that right after you call InitializeComponent(); in your main form :) – Luke Briggs Oct 13 '13 at 00:54
  • I added it to the Initialize Component(); and then to after it on the main form, and it showed up as an error. – user2635167 Oct 14 '13 at 19:31
  • I changed it to optimizeddoublebuffer, and that works, but it doesnt like setstyle – user2635167 Oct 14 '13 at 19:33