8 Replies - 422 Views - Last Post: 18 February 2013 - 08:09 AM Rate Topic: -----

#1 triangulator  Icon User is offline

  • New D.I.C Head

Reputation: -1
  • View blog
  • Posts: 27
  • Joined: 03-February 13

How to remove blinking when refreshing a control's paint method?

Posted 17 February 2013 - 05:49 AM

I have a few classes that inherit an abstract class and need to draw things, a timer and a sub-window on which things are to be drawn. I need the drawn things to respond to the cursor position in real time, so I have set the timer to 17 miliseconds (which is 60 fps, about the rate of which human eye functions) and in the timer tick method of the class I have the following code:
void tick(object sender, EventArgs e)
        {
            //some other code
            drawwindow.Refresh();
        }


Now in the draw window itself, I have manually defined the paint event:
        public void drawingwindow_Paint(object sender, PaintEventArgs e)
        {
            ris = this.CreateGraphics();
            ris.DrawEllipse(pisec, pointa.X - 10, pointa.Y - 10, 20, 20);
            ris.DrawEllipse(pisec, pointb.X - 10, pointb.Y - 10, 20, 20);
            ris.DrawEllipse(pisec, pointc.X - 10, pointc.Y - 10, 20, 20);
            ris.DrawLine(pisec, new Point(100, 100), PointToClient(Cursor.Position));
            ris.Dispose();
            //if (owner != null) owner.draw();
        }


The above code runs just fine, no blinking. The thing is, it is just a test code and I need the commented line to draw the stuff:
        public void drawingwindow_Paint(object sender, PaintEventArgs e)
        {
            if (owner != null) owner.draw();
        }


Using the latter code instead of the former one results in that the drawing window constantly blinks, which is very annoying to the eye. Apparently all the draw code needs to be in the paint method.

I could technically transfer the code of the owner in the paint method. The problem is that 'owner' can be an instance of several classes, each of which has a draw method with several hundred lines of code. Thus the paint method would look something like this:
        public void drawingwindow_Paint(object sender, PaintEventArgs e)
        {
            if (owner != null)
                {
                if (typeof(owner)==Triangle)
                    {
                    //like 500 lines of code here...
                    }
                if (typeof(owner)==Circle)
                    {
                    //more 500 lines of code here...
                    }
                //etc.
                }
        }


And then I'd need to prefix all properties with respectively ((Triangle)owner)., ((Circle)owner)., etc.
This is certainly not the way I want to go about the issue.

Then I thought I'd set the timer rate to the refresh rate of the display, but when I looked where I can obtain this information, I couldn't find a thing.
I can always set the rate of the timer to say half a second, but this does not remove the blinking, it only slows it down, so it's not an option.

How can I solve this problem? Thanks in advance.

Is This A Good Question/Topic? 0
  • +

Replies To: How to remove blinking when refreshing a control's paint method?

#2 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5509
  • View blog
  • Posts: 11,814
  • Joined: 02-June 10

Re: How to remove blinking when refreshing a control's paint method?

Posted 17 February 2013 - 06:52 AM

Using a timer and polling is already going down the wrong path.

C# and .NET are meant to be event driven. Why paint when there has been no change? Instead of the timer just react to the mouse movement. Only repaint as the mouse gets moved.

Repainting the parent control is going to result in its children being repainted. So if your child is triggering the parent to repaint (a design flaw in your logic) then you have this loop of cascading continual repainting.

A paint
  |
  B paint
     |
     C paint
       |
        Order A to repaint


Quote

07      //like 500 lines of code here...


If you have 500+ lines of code in one if statement, you need to put that in its own method. And I'd bet that it is 'brute force' code that can probably be reduced.
Was This Post Helpful? 1
  • +
  • -

#3 triangulator  Icon User is offline

  • New D.I.C Head

Reputation: -1
  • View blog
  • Posts: 27
  • Joined: 03-February 13

Re: How to remove blinking when refreshing a control's paint method?

Posted 17 February 2013 - 07:16 AM

View PosttlhIn`toq, on 17 February 2013 - 06:52 AM, said:

Using a timer and polling is already going down the wrong path.

C# and .NET are meant to be event driven. Why paint when there has been no change? Instead of the timer just react to the mouse movement. Only repaint as the mouse gets moved.


Okay, now I use this code:
        private void drawingwindow_MouseMove(object sender, MouseEventArgs e)
        {
            owner.reacttomovement();
        }



public void reacttomovement()
        {
            //some other code
            drawwindow.Refresh();
        }


And still the blinking remains.

View PosttlhIn`toq, on 17 February 2013 - 06:52 AM, said:

Repainting the parent control is going to result in its children being repainted. So if your child is triggering the parent to repaint (a design flaw in your logic) then you have this loop of cascading continual repainting.

A paint
  |
  B paint
     |
     C paint
       |
        Order A to repaint


The method owner.draw does not repaint the parent control. Instead, the parent paints on behalf on the drawingwindow:
        public override void draw()
        {
           drawwindow.creategrafix();
           //some math
            drawwindow.grafix.DrawLine(drawwindow.thickpen, pointA, pointB);
            drawwindow.grafix.DrawLine(drawwindow.thickpen, pointA, pointC);
            drawwindow.grafix.DrawLine(drawwindow.thickpen, pointC, pointB);
           //some more drawing
           drawwindow.disposegrafix();
         }


Note that these parent classes that own drawingwindow have no forms or windows by themselves - they are merely classes, not any of the Controls.
So there is no such loop.

View PosttlhIn`toq, on 17 February 2013 - 06:52 AM, said:

Quote

07      //like 500 lines of code here...


If you have 500+ lines of code in one if statement, you need to put that in its own method. And I'd bet that it is 'brute force' code that can probably be reduced.

In case I misexpressed myself, the code you quoted is what I could do, but what I don't and don't want to do.
Every of those about 500 lines of code is in its own method (the draw of the owner).
Was This Post Helpful? 0
  • +
  • -

#4 Skydiver  Icon User is online

  • Code herder
  • member icon

Reputation: 3570
  • View blog
  • Posts: 11,095
  • Joined: 05-May 12

Re: How to remove blinking when refreshing a control's paint method?

Posted 17 February 2013 - 11:10 AM

Can you show us as example of the implementations for Triange.draw(), or Line.draw()? Is the second chunk of code that you posted in Post #1 representative of the other draw() methods?

On a high level first:
If so, there is nothing there that should cause any blinking. Blinking happens when entire areas are erased, and then drawn in. If on the other hand, your various draw() methods fill or erase their areas first, then you are setting yourself up for some blinking.

Now on to details:
You don't need to create Graphics object. You are given one in the PaintEventArgs. Just pass that object around.

Have you turned on double buffering for your form?
Was This Post Helpful? 1
  • +
  • -

#5 triangulator  Icon User is offline

  • New D.I.C Head

Reputation: -1
  • View blog
  • Posts: 27
  • Joined: 03-February 13

Re: How to remove blinking when refreshing a control's paint method?

Posted 17 February 2013 - 12:14 PM

View PostSkydiver, on 17 February 2013 - 11:10 AM, said:

Can you show us as example of the implementations for Triange.draw(), or Line.draw()? Is the second chunk of code that you posted in Post #1 representative of the other draw() methods?

On a high level first:
If so, there is nothing there that should cause any blinking. Blinking happens when entire areas are erased, and then drawn in. If on the other hand, your various draw() methods fill or erase their areas first, then you are setting yourself up for some blinking.

Now on to details:
You don't need to create Graphics object. You are given one in the PaintEventArgs. Just pass that object around.

Have you turned on double buffering for your form?

1. - Well, I guess you won't bother to look at all of the code, so I'll give you only the part that actually draws, without the calculations(so don't mind the undeclared variables). Also, I can't be bothered to deobfuscate code that long.
Triangle.draw():
Spoiler

Basically, between almost every two lines there is some additional code that does the math.

2. If we ignore that it lacks the math and that it draws different things, yes, it is.
3. Well, that was it. :)/> I'd never figure out on my own that there is no need of manually emptying the drawing surface in a blank colour. I thought that the previous graphics would stay there if the canvas wasn't refilled.
4. I thought PaintEventArgs is different every time the Paint event is called?
5. I don't know what that is.
6. Also, why can I vote only once?
Was This Post Helpful? 0
  • +
  • -

#6 Skydiver  Icon User is online

  • Code herder
  • member icon

Reputation: 3570
  • View blog
  • Posts: 11,095
  • Joined: 05-May 12

Re: How to remove blinking when refreshing a control's paint method?

Posted 17 February 2013 - 01:22 PM

Yes, the instance of PaintEventArgs that is passed to the Paint event is different every time, but the Graphics object within thin PaintEventArgs is the Graphics object that is associated with the control that is receiving the paint event.

You can read about double buffering in MSDN: http://msdn.microsof...y/3t7htc9c.aspx
Was This Post Helpful? 1
  • +
  • -

#7 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5509
  • View blog
  • Posts: 11,814
  • Joined: 02-June 10

Re: How to remove blinking when refreshing a control's paint method?

Posted 17 February 2013 - 02:07 PM

View Posttriangulator, on 17 February 2013 - 01:14 PM, said:

1. - Well, I guess you won't bother to look at all of the code,

That's bright - insult the people helping you.

You are causing a lot of extra checking of the GUI and that is very slow to happen.

Quote

 if (c.Vidise == CheckState.Checked)
45            ris.ris.DrawString("c = " + c.Value.ToString(), ris.pis, ris.ket, funkcii.premest2(tb,ta, rast), ris.sf);
46            else if (c.Vidise != CheckState.Unchecked)


Line 46 doesn't have to check the state of the checkbox since you just determined on line 45 that it wasn't checked. Line 46 won't run if the checkbox is checked

This post has been edited by tlhIn`toq: 17 February 2013 - 02:07 PM

Was This Post Helpful? 0
  • +
  • -

#8 triangulator  Icon User is offline

  • New D.I.C Head

Reputation: -1
  • View blog
  • Posts: 27
  • Joined: 03-February 13

Re: How to remove blinking when refreshing a control's paint method?

Posted 18 February 2013 - 05:02 AM

View PosttlhIn`toq, on 17 February 2013 - 02:07 PM, said:

View Posttriangulator, on 17 February 2013 - 01:14 PM, said:

1. - Well, I guess you won't bother to look at all of the code,

That's bright - insult the people helping you.

You are causing a lot of extra checking of the GUI and that is very slow to happen.

Quote

 if (c.Vidise == CheckState.Checked)
45            ris.ris.DrawString("c = " + c.Value.ToString(), ris.pis, ris.ket, funkcii.premest2(tb,ta, rast), ris.sf);
46            else if (c.Vidise != CheckState.Unchecked)


Line 46 doesn't have to check the state of the checkbox since you just determined on line 45 that it wasn't checked. Line 46 won't run if the checkbox is checked

I didn't intend to insult anyone - I genuinely don't think anyone will look at code that long now after the problem is solved.
The checkbox of user control 'c' is a three state one, so it could be CheckState.Indeterminate as well.
Was This Post Helpful? 0
  • +
  • -

#9 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5509
  • View blog
  • Posts: 11,814
  • Joined: 02-June 10

Re: How to remove blinking when refreshing a control's paint method?

Posted 18 February 2013 - 08:09 AM

Ok. I stand corrected.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1