Results 1 to 13 of 13

Thread: Why does the Form_Paint event run continuously but only draw once ?

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Mar 2008
    Posts
    517

    Why does the Form_Paint event run continuously but only draw once ?

    I have the following code, I put a label in Form_Paint to track the number jump, I see the label jumping continuously but e.Graphics.DrawString(...) only looks once, does anyone know why ?

    Code:
    public partial class Form1 : Form
        {       
            public Form1()
            {
                InitializeComponent();            
                progressBar1.Minimum = 0;
                progressBar1.Maximum = 100;
    
                this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form1_Paint);
    
            }
            int iNum = 0;       
            private void btnDrawText_Click(object sender, EventArgs e) //PaintEventArgs e
            {           
                progressBar1.Value = 0;
                progressBar1.Visible = true;
                this.timer1.Interval = 100;
                this.timer1.Enabled = true;           
                           
            }
            private void ShadowedTextPaint(PaintEventArgs e, int num)
            {
                using (Font font1 = new Font("Times New Roman", 250, FontStyle.Bold, GraphicsUnit.Pixel))
                {
                    PointF pointF1 = new PointF(310, 270);
                    e.Graphics.DrawString(num.ToString(), font1, Brushes.LightGreen, pointF1);               
                    lblNum.Text = num.ToString();
                }           
               
            }
            private void Form1_Paint(object sender, PaintEventArgs e)
            {
                ShadowedTextPaint(e, iNum);
            }
            protected override void OnPaint(PaintEventArgs e)
            {
                // call base
                base.OnPaint(e);
    
                e.Graphics.DrawString(this.iNum.ToString(), Font, new SolidBrush(ForeColor), ClientRectangle);
                lblNum.Text = iNum.ToString();
                
            }
            private void timer1_Tick(object sender, EventArgs e)
            {           
                if (progressBar1.Value < 100)
                {               
                    Random rd = new Random();
                    iNum = rd.Next(0, 999);               
                    progressBar1.Value++;
                }
                else
                {               
                    this.timer1.Enabled = false;
                    progressBar1.Visible = false;               
                }
               
            }
      }

  2. #2
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,299

    Re: Why does the Form_Paint event run continuously but only draw once ?

    First things first, why are you overriding OnPaint and handling Paint? You do one or the other. If you would handle the Load event of the form rather than overriding OnLoad then you should handle the Paint event rather than overriding OnPaint.

    As for your question, the Label gets updated immediately after you call DrawString so it is literally impossible that the the Label gets updated without DrawString being called. If there's a problem it's clearly with how you're looking at it, not what it's doing.

    Also, I don't see any calls to Invalidate in there. One would think that you would want to force a repaint when the Timer Ticks, so it seems logical to call Invalidate in the Tick event handler.

  3. #3
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,299

    Re: Why does the Form_Paint event run continuously but only draw once ?

    Another point: if you're going to call a method to do the drawing, logic dictates that you pass it a Graphics object, not a PaintEventArgs object. You're not going to use anything but the Graphics object in the method so you shouldn't be passing anything more than that. It also means that you can call that method with any Graphics object, e.g. the result of Graphics.FromImage, rather than just on a Paint event.

  4. #4
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: Why does the Form_Paint event run continuously but only draw once ?

    I'm thinking that changing the progressbar is causing a form paint event, but the bounds of the update are limited to the area of the progressbar so any additional drawing you are doing in the paint event is not seen (it is clipped), until such point as Windows decides it should invalidate the whole form for "clean up", so you see one update with your drawing.

    As jmc says, if you had an Invalidate in your tick event, then you would be causing a paint event, with the whole form being included in the update region.
    Of course, at least since you've had this "problem", you can fix the other issues jmc has pointed out. Personally, I would create the random object once at form class scope, and use it in the timer rather than create one each tick.
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  5. #5

    Thread Starter
    Fanatic Member
    Join Date
    Mar 2008
    Posts
    517

    Re: Why does the Form_Paint event run continuously but only draw once ?

    Hi all friend!

    I used the OnPaint override here because I call's the drawing methods in the Form_Paint event but i didn't see the drawing again, while the label control jumped continuously, you told me that I haven't calls to Invalidate in there, thank you for sharing my knowledge. I just started to learn about graphics knowledge, I am too weak.

    Now my program has been jumping random numbers but the screen is jerky, shaky, jerked very hard ... when the program ran continuously. I think using graphics to draw numbers continuously will produce a smoother images but it's not as my expected, I use the Form_Paint event even worse when I use the label control to skip a number continuously.

    In your opinion, is there any way to use Form_Paint to draw random numbers continuously over time so that the screen does not vibrate, get jerked, or get jigged violently ...?

  6. #6
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: Why does the Form_Paint event run continuously but only draw once ?

    Try setting the "DoubleBuffered" property of the form to True, to see if it doesn't look better.
    Personally, I usually put a Picturebox on the form and size it to what I want and draw in it.

    The Picturebox is DoubledBuffered by default, so is designed with the idea that it will be drawn in. The form is designed for hosting controls and generally a static background. You can draw on it, as you can draw on any control in .Net, but it has a lot of other duties in maintaining the overall window, and I've found it to not always be the best surface to use as a continual updating drawing. The drawing update I've found to slower in some cases compared to drawing in a picturebox.

    Once you set the DoubledBuffered property, I expect things will look much better in any case.

    p.s. I'm assuming you removed the OnPaint code, otherwise you're drawing the form twice each update, so doing the twice the work you need to, and making things look worse than they would have, even with DoubledBuffered set to False.
    Last edited by passel; Oct 24th, 2019 at 04:55 AM.
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  7. #7

    Thread Starter
    Fanatic Member
    Join Date
    Mar 2008
    Posts
    517

    Re: Why does the Form_Paint event run continuously but only draw once ?

    Hi passel!

    According to your instructions, my program has run very well with no shaking screen, no stutter, ... Thank you all friend for sharing my knowledge but I still have a question related to the article hey, in the above example, I deleted the Form_Paint event to redraw the word, I will rewrite the timer1_Tick event as follows:

    Code:
    private void timer1_Tick(object sender, EventArgs e)
            {
                if (progressBar1.Value < 100)
                {
                    Random rd = new Random();
                    iNum = rd.Next(0, 999);                
                    using (Graphics g = this.CreateGraphics())                
                    {
                        // Set up the font
                        Font fnt = new Font("Calibri", 150, FontStyle.Bold | FontStyle.Italic, GraphicsUnit.Point);
    
                        // Draw background text
                        g.DrawString(iNum.ToString(), fnt, Brushes.DarkGray, 244, 274);
    
                        // Draw main text slightly offset from shadow text
                        g.DrawString(iNum.ToString(), fnt, Brushes.Aqua, 240, 270);
    
                    }                
                    lblNum.Text = iNum.ToString();
    
                    progressBar1.Value++;                
                }
                else
                {                
                    this.timer1.Enabled = false;
                    progressBar1.Visible = false;
                }
    
            }
    My question is: after drawing the word, I want to delete the word I just finished writing (can say undo it, remove it or restore it before drawing the word) because in this example the random number jumps repeatedly overwritten continuously, in your opinion, is there a way to avoid continuous overriding for the timer1_Tick event ?

  8. #8
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,299

    Re: Why does the Form_Paint event run continuously but only draw once ?

    Wow! After all this time you are STILL insisting on doing it the wrong way. If you had done as instructed, i.e. called Invalidate and done the drawing in the Paint event handler, then this issue of the old drawing not disappearing would never have occurred. I felt a little bad that I may have been too hard on you but it turns out that I wasn't hard enough. You are literally wasting your time and everyone else's by refusing to do things the proper way despite having been to do so and why on multiple occasions. If you're going to ignore sound advice then I guess my Ignore list is the appropriate place for you.

  9. #9

    Thread Starter
    Fanatic Member
    Join Date
    Mar 2008
    Posts
    517

    Re: Why does the Form_Paint event run continuously but only draw once ?

    Sorry you jmcilhinney!
    My English is not good, I read the word missing so I misunderstood, now I understand, thank you very much

  10. #10
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,299

    Re: Why does the Form_Paint event run continuously but only draw once ?

    Here's a very simple example:
    vb.net Code:
    1. Private textDrawingArea As New Rectangle(10, 10, 100, 25)
    2.  
    3. Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    4.     Invalidate(textDrawingArea)
    5. End Sub
    6.  
    7. Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
    8.     e.Graphics.DrawString(Date.Now.ToString("t"), Font, Brushes.Black, textDrawingArea)
    9. End Sub
    The Invalidate call basically says repaint everything in this area and then forces a Paint event to be raised. The drawing is then done in the area that was invalidated. That effectively erases the old drawing and does the new. You can call Invalidate without an argument and it will repaint the whole form, but that is inefficient if you know that most of it won't have changed. You can call Invalidate multiple times if multiple separate (possibly overlapping) areas may have changed, e.g.
    vb.net Code:
    1. Private topLeftDrawingArea As New Rectangle(10, 10, 100, 25)
    2. Private bottomRightDrawingArea As Rectangle = GetBottomRightDrawingArea()
    3.  
    4. Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    5.     'Repaint the static area.
    6.     Invalidate(topLeftDrawingArea)
    7.  
    8.     'Repaint the old changeable area.
    9.     Invalidate(bottomRightDrawingArea)
    10.  
    11.     'Calculate the new changeable drawing area, in case the form has changed size.
    12.     bottomRightDrawingArea = GetBottomRightDrawingArea()
    13.  
    14.     'Repaint the new changeable area.
    15.     Invalidate(bottomRightDrawingArea)
    16. End Sub
    17.  
    18. Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
    19.     e.Graphics.DrawString(Date.Now.ToString("d"), Font, Brushes.Black, topLeftDrawingArea)
    20.     e.Graphics.DrawString(Date.Now.ToString("t"), Font, Brushes.Black, bottomRightDrawingArea)
    21. End Sub
    22.  
    23. Private Function GetBottomRightDrawingArea() As Rectangle
    24.     Return New Rectangle(ClientSize.Width - 10 - 100, ClientSize.Height - 10 - 25, 100, 25)
    25. End Function

  11. #11

    Thread Starter
    Fanatic Member
    Join Date
    Mar 2008
    Posts
    517

    Re: Why does the Form_Paint event run continuously but only draw once ?

    Hi jmcilhinney!
    Now I understand you jmcilhinney, the program runs fine in both cases with or without the Form_Paint event. Thank you all friend.

  12. #12
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,299

    Re: Why does the Form_Paint event run continuously but only draw once ?

    Quote Originally Posted by dong View Post
    the program runs fine in both cases with or without the Form_Paint event.
    Are you seriously suggesting that you would still try to draw on a form without handling the Paint event?

  13. #13

    Thread Starter
    Fanatic Member
    Join Date
    Mar 2008
    Posts
    517

    Re: Why does the Form_Paint event run continuously but only draw once ?

    I studied programming with graphics in C#, so I tried writing a random number jump program for both cases with the Form_Paint event and no Form_Paint event, The follow me seen, there is a Form_Paint event, the program draws more beautiful pictures than there is no Form_Paint event so I still prefer to use the Form_Paint event to write my own applications.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width