Results 1 to 13 of 13

Thread: [RESOLVED] Stop graphics ellipse trail

  1. #1

    Thread Starter
    Member
    Join Date
    Aug 2015
    Posts
    40

    Resolved [RESOLVED] Stop graphics ellipse trail

    Hi All,

    I'm using .Net Visual Studio 2015 Windows Forms Application

    I'm writing an application that uses values from a database and draws an ellipse in a certain colour depending on the database value. For example: if the value was 10 then the ellipse would be blue but if the value was 20 then the colour would be red.

    All of these drawing commands are being used in the paint event of a picturebox on my form.

    This works fine.

    Now I want the ability to move the ellipses so I'm using trackbars to change the position of the ellipse. As I change the position of the ellipse it leaves a "trail" behind of previously drawn ellipses in their old positions. I thought I could solve this be reloading the image by updating the pciturebox.image property at the start of my code. This does work in terms of getting rid of the "trail" but it also removes the ellipses when i let go of the trackbar. This gives me a strobing effect when i move the trackbar but no final drawn ellipse.

    How do I get my drawn ellipse to stay visible while also stop it from leaving a trail?

    Regards

    Steve

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

    Re: Stop graphics ellipse trail

    When the Paint event is raised, everything in an area of the control that has been invalidated since the last Paint event is erased. If you're not seeing some of your old drawing erased then it's because you're not invalidating that area. We can't really tell you more specifically what you're doing wrong as you've chosen to ask us for help with code that you've chosen not to show us.

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

    Re: Stop graphics ellipse trail

    You're appear to be drawing from the trackbar event. Don't draw from the trackbar event.
    You want to update a variable (the offset for the ellipse) in the trackbar event and then invalidate the picturebox so the paint event will happen. In the paint event use the variable when drawing the ellipse. If the ellipse lags too much because you move the trackbar quickly, you may want to use refresh instead of invalidate. The drawing will be slower, but it will happen as fast as it can and immediately so will appear to track the trackbar movement better.
    Last edited by passel; Oct 16th, 2017 at 12:02 PM.

  4. #4

    Thread Starter
    Member
    Join Date
    Aug 2015
    Posts
    40

    Re: Stop graphics ellipse trail

    Thanks for the reply guys.

    I know it's taken a long time for me to reply, I had to move on to other projects and only just returned to this. I choose not to include any code as I thought it might distract from my problem I'll post my code below:

    Code:
      Sub test()
    
    
            SubCount = SubCount + 1
    
            Dim g As Graphics = PictureBox1.CreateGraphics
    
            Me.TextBox3.Text = Me.Db14DataSet.Table1.Rows(GloNum).Item("sp1")
            Me.TextBox4.Text = Me.Db14DataSet.Table1.Rows(GloNum).Item("sp2")
            Me.TextBox5.Text = Me.Db14DataSet.Table1.Rows(GloNum).Item("sp3")
            Me.TextBox6.Text = Me.Db14DataSet.Table1.Rows(GloNum).Item("sp4")
            Me.TextBox7.Text = Me.Db14DataSet.Table1.Rows(GloNum).Item("sp5")
            Me.TextBox8.Text = Me.Db14DataSet.Table1.Rows(GloNum).Item("sp6")
            Me.TextBox9.Text = Me.Db14DataSet.Table1.Rows(GloNum).Item("sp7")
            Me.TextBox10.Text = Me.Db14DataSet.Table1.Rows(GloNum).Item("sp8")
            Me.TextBox11.Text = Me.Db14DataSet.Table1.Rows(GloNum).Item("sp9")
            Me.TextBox12.Text = Me.Db14DataSet.Table1.Rows(GloNum).Item("sp10")
            Me.TextBox13.Text = Me.Db14DataSet.Table1.Rows(GloNum).Item("sp11")
            Me.TextBox14.Text = Me.Db14DataSet.Table1.Rows(GloNum).Item("sp12")
            Me.TextBox15.Text = Me.Db14DataSet.Table1.Rows(GloNum).Item("sp13")
            Me.TextBox16.Text = Me.Db14DataSet.Table1.Rows(GloNum).Item("sp14")
            Me.TextBox17.Text = Me.Db14DataSet.Table1.Rows(GloNum).Item("sp15")
            Me.TextBox18.Text = Me.Db14DataSet.Table1.Rows(GloNum).Item("ID")
    
            Dim dave
            Dim setpoint
            Dim circleSize
    
            Dim C1_Xpos
            Dim C2_Xpos
            Dim C3_Xpos
            Dim C4_Xpos
            Dim C5_Xpos
            Dim C6_Xpos
            Dim C7_Xpos
            Dim C8_Xpos
            Dim C9_Xpos
            Dim C10_Xpos
            Dim C11_Xpos
            Dim C12_Xpos
            Dim C13_Xpos
            Dim C14_Xpos
            Dim C15_Xpos
    
            Dim C1_Ypos
            Dim C2_Ypos
            Dim C3_Ypos
            Dim C4_Ypos
            Dim C5_Ypos
            Dim C6_Ypos
            Dim C7_Ypos
            Dim C8_Ypos
            Dim C9_Ypos
            Dim C10_Ypos
            Dim C11_Ypos
            Dim C12_Ypos
            Dim C13_Ypos
            Dim C14_Ypos
            Dim C15_Ypos
    
            circleSize = 28
    
    
            'Circle 1 X and Y postion
            C1_Xpos = TrackBarX.Value
            C1_Ypos = TrackBarY.Value
    
            ''''Circle 1 X and Y postion
            '''C1_Xpos = 125
            '''C1_Ypos = 342
    
            'Circle 2 X and Y postion
            C2_Xpos = 170
            C2_Ypos = 364
    
            'Circle 3 X and Y postion
            C3_Xpos = 195
            C3_Ypos = 330
    
            'Circle 4 X and Y postion
            C4_Xpos = 231
            C4_Ypos = 290
    
            'Circle 5 X and Y postion
            C5_Xpos = 275
            C5_Ypos = 311
    
            'Circle 6 X and Y postion
            C6_Xpos = 125
            C6_Ypos = 342 + 92
    
            'Circle 7 X and Y postion
            C7_Xpos = C2_Xpos
            C7_Ypos = C2_Ypos + 92
    
            'Circle 8 X and Y postion
            C8_Xpos = C3_Xpos
            C8_Ypos = C3_Ypos + 92
    
            'Circle 9 X and Y postion
            C9_Xpos = C4_Xpos
            C9_Ypos = C4_Ypos + 92
    
            'Circle 10 X and Y postion
            C10_Xpos = C5_Xpos
            C10_Ypos = C5_Ypos + 92
    
            'Circle 11 X and Y postion
            C11_Xpos = 125
            C11_Ypos = 342 + 190
    
            'Circle 12 X and Y postion
            C12_Xpos = C2_Xpos
            C12_Ypos = C2_Ypos + 190
    
            'Circle 13 X and Y postion
            C13_Xpos = C3_Xpos
            C13_Ypos = C3_Ypos + 190
    
            'Circle 14 X and Y postion
            C14_Xpos = C4_Xpos
            C14_Ypos = C4_Ypos + 190
    
            'Circle 15 X and Y postion
            C15_Xpos = C5_Xpos
            C15_Ypos = C5_Ypos + 190
    
    
    
            setpoint = Val(TextBox3.Text)
            dave = ColourChoose(setpoint)
            Dim myBrush As New System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(RedGreenBlue(1), RedGreenBlue(2), RedGreenBlue(3)))
            g.FillEllipse(myBrush, C1_Xpos, C1_Ypos, circleSize, circleSize)
    
    
    
    
            setpoint = Val(TextBox4.Text)
            dave = ColourChoose(setpoint)
            Dim myBrush2 As New System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(RedGreenBlue(1), RedGreenBlue(2), RedGreenBlue(3)))
            g.FillEllipse(myBrush2, C2_Xpos, C2_Ypos, circleSize, circleSize)
    
    
    
    
            setpoint = Val(TextBox5.Text)
            dave = ColourChoose(setpoint)
            Dim myBrush3 As New System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(RedGreenBlue(1), RedGreenBlue(2), RedGreenBlue(3)))
            g.FillEllipse(myBrush3, C3_Xpos, C3_Ypos, circleSize, circleSize)
    
    
    
    
            setpoint = Val(TextBox6.Text)
            dave = ColourChoose(setpoint)
            Dim myBrush4 As New System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(RedGreenBlue(1), RedGreenBlue(2), RedGreenBlue(3)))
            g.FillEllipse(myBrush4, C4_Xpos, C4_Ypos, circleSize, circleSize)
    
    
    
    
            setpoint = Val(TextBox7.Text)
            dave = ColourChoose(setpoint)
            Dim myBrush5 As New System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(RedGreenBlue(1), RedGreenBlue(2), RedGreenBlue(3)))
            g.FillEllipse(myBrush5, C5_Xpos, C5_Ypos, circleSize, circleSize)
    
    
    
            setpoint = Val(TextBox8.Text)
            dave = ColourChoose(setpoint)
            Dim myBrush6 As New System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(RedGreenBlue(1), RedGreenBlue(2), RedGreenBlue(3)))
            g.FillEllipse(myBrush6, C6_Xpos, C6_Ypos, circleSize, circleSize)
    
    
    
            setpoint = Val(TextBox9.Text)
            dave = ColourChoose(setpoint)
            Dim myBrush7 As New System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(RedGreenBlue(1), RedGreenBlue(2), RedGreenBlue(3)))
            g.FillEllipse(myBrush7, C7_Xpos, C7_Ypos, circleSize, circleSize)
    
    
    
            setpoint = Val(TextBox10.Text)
            dave = ColourChoose(setpoint)
            Dim myBrush8 As New System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(RedGreenBlue(1), RedGreenBlue(2), RedGreenBlue(3)))
            g.FillEllipse(myBrush8, C8_Xpos, C8_Ypos, circleSize, circleSize)
    
    
    
            setpoint = Val(TextBox11.Text)
            dave = ColourChoose(setpoint)
            Dim myBrush9 As New System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(RedGreenBlue(1), RedGreenBlue(2), RedGreenBlue(3)))
            g.FillEllipse(myBrush9, C9_Xpos, C9_Ypos, circleSize, circleSize)
    
            setpoint = Val(TextBox12.Text)
            dave = ColourChoose(setpoint)
            Dim myBrush10 As New System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(RedGreenBlue(1), RedGreenBlue(2), RedGreenBlue(3)))
            g.FillEllipse(myBrush10, C10_Xpos, C10_Ypos, circleSize, circleSize)
    
            setpoint = Val(TextBox13.Text)
            dave = ColourChoose(setpoint)
            Dim myBrush11 As New System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(RedGreenBlue(1), RedGreenBlue(2), RedGreenBlue(3)))
            g.FillEllipse(myBrush11, C11_Xpos, C11_Ypos, circleSize, circleSize)
    
    
    
            setpoint = Val(TextBox14.Text)
            dave = ColourChoose(setpoint)
            Dim myBrush12 As New System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(RedGreenBlue(1), RedGreenBlue(2), RedGreenBlue(3)))
            g.FillEllipse(myBrush12, C12_Xpos, C12_Ypos, circleSize, circleSize)
    
    
    
            setpoint = Val(TextBox15.Text)
            dave = ColourChoose(setpoint)
            Dim myBrush13 As New System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(RedGreenBlue(1), RedGreenBlue(2), RedGreenBlue(3)))
            g.FillEllipse(myBrush13, C13_Xpos, C13_Ypos, circleSize, circleSize)
    
    
    
            setpoint = Val(TextBox16.Text)
            dave = ColourChoose(setpoint)
            Dim myBrush14 As New System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(RedGreenBlue(1), RedGreenBlue(2), RedGreenBlue(3)))
            g.FillEllipse(myBrush14, C14_Xpos, C14_Ypos, circleSize, circleSize)
    
    
    
            setpoint = Val(TextBox17.Text)
            dave = ColourChoose(setpoint)
            Dim myBrush15 As New System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(RedGreenBlue(1), RedGreenBlue(2), RedGreenBlue(3)))
            g.FillEllipse(myBrush15, C15_Xpos, C15_Ypos, circleSize, circleSize)
    
    
    
        End Sub

    Yes, I know there's much to be desired in the formatting and i'm sure it's quite inefficient but it works.

    I'm calling this sub from the trackbar control scroll event.


    Code:
        Private Sub TrackBarY_Scroll(sender As Object, e As EventArgs) Handles TrackBarY.Scroll
    
    
            TextBoxYSlider.Text = TrackBarY.Value
    
            TrackbarYValue = TrackBarY.Value
    
            PictureBox1.Invalidate()
    
            test()
    
        End Sub
    I've actually (Sort of) fixed the problem. If i put a messagebox in the Trackbar mouse up event then call the sub again, the message displays and the graphics stay there.

    Code:
        Private Sub TrackBarY_MouseUp(sender As Object, e As MouseEventArgs) Handles TrackBarY.MouseUp
            
            MsgBox(SubCount)
            test()
        End Sub
    As to why this works i don't know and also i don't really want to have a message box display at all

  5. #5
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,989

    Re: Stop graphics ellipse trail

    I'd say that JMC explained why the messagebox is fixing the issue. When that goes away, the underlying form is probably invalidated, which removes all of your previous drawing. You then just draw it again, and it looks like it works. If that theory is correct, you could replace the messagebox with Me.Referesh and see the same thing.

    That would be REALLY inefficient, though, and I'm not endorsing that as a solution, but it would be a reasonable test. Me.Invalidate wouldn't work, because it would leave the painting till later. In fact, it will leave it until after Test, so it should clear the screen completely. Me.Referesh would force the drawing to be done right away, before Test is even run.

    What you should be doing is taking the advice in the previous posts. Drawing the way you are doing may be fine for this use. That's up to you. If the performance is fine, then it's probably okay, though you should be explicitly disposing of some of those items. However, it's not good practice, so you'd be learning bad habits that will fail once you start doing more costly drawing.
    My usual boring signature: Nothing

  6. #6
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Stop graphics ellipse trail

    Technically the problem is you lied to us.

    You said:
    All of these drawing commands are being used in the paint event of a picturebox on my form.
    What you did instead:
    Sub test()
    SubCount = SubCount + 1

    Dim g As Graphics = PictureBox1.CreateGraphics
    That is not "the paint event of a PictureBox", and if you'd posted this code we could've given you an answer 2 weeks ago. Let's go over it, this is one of the most common mistakes people make in VB programming because every bad tutorial by every village idiot uses this approach.

    To get to a Paint event, all of this happens:
    1. Something happens that makes Windows decide your Form needs repainting.
    2. Windows sends WM_PAINT to your form's message queue.
    3. Your form sees WM_PAINT and starts responding.
    4. The Form creates a Graphics object.
    5. The Form calls some method that erases the background with a name I can't find.
    6. The Form calls OnPaint(), which raises the Paint event.
    7. You get to draw on the blank Form.

    The same thing happens with more or less every control. Paint event handlers are the last step in the whole drawing process. The important thing here is Windows never "remembers" what you drew. Every cycle, the entire thing is erased and redrawn.

    Here's what happens when you use CreateGraphics():
    1. A Graphics object is given to you.
    2. You draw.

    The background is not erased. The last thing you drew isn't erased. The next time a Paint cycle happens, whatever you drew will be erased. The only way you can know when this happens is to handle the Paint event.

    So it turns out it is never right to use CreateGraphics() to draw at a random time. You should always set up whatever variables you need to draw, then call Invalidate(). This will erase everything and raise the Paint event so you can draw on a fresh canvas. I wish I could delete every tutorial that uses CreateGraphics() from the internet and get the people who wrote them banned from the internet. The closest I can come is to say, "If you see a tutorial that suggests CreateGraphics(), read every sentence as "BOY I SURE LIKE EATING ALL THIS LEAD PAINT AND ARSENIC, I AM THE SMARTEST PERSON IN THE WORLD, TIME TO GO WRITE TUTORIALS HA HA"".

    It never works, it's never right.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

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

    Re: Stop graphics ellipse trail

    <edit>never mind, SS replied while I was composing so this is a shorter, redundant version of what he posted</edit>

    You said your were doing all your drawing from the paint event. You should continue to do that even for your dynamic moving.
    Instead of calling test() from your trackbar routine, you should either add the code from test to your paint event and using the e.Graphics object provided, or calling test() from your paint event, passing it the e.Graphics object provided by paint. That would eliminate strobing, trails and loss of ellipses on mouse up.
    You can add a boolean value that is set in the trackbar routine if needed so that the paint event can skip the code if it isn't necessary to use the trackbar value when the window needs repainting "normally".

  8. #8

    Thread Starter
    Member
    Join Date
    Aug 2015
    Posts
    40

    Re: Stop graphics ellipse trail

    Thanks for all help so far guys,

    Yes the me.refresh trick did fix it so you're definitely right in your assumptions. There's been a bit of confusion, I was originally using the paint event to draw my graphics objects but as I was having trouble I made a separate sub routine just to test it (hence why it's called test). Following everyone's advice here I was able to get it to work properly in a sub routine because I can use the me.refresh command to invalidate the form and then call my sub one final time to keep the graphics visible.

    If I move the code back to the paint event then it strobes (as it does with the subroutine) but it only stays visible when I let go of the track bar sometimes.

    To try to understand what was happening i used a message box to display the number of times the subroutine had run to see if the graphics stayed on the screen on odd or even numbers of calls. I couldn't find a pattern because the message box ended up fixing the problem!

    So while I appreciate everyone's help here I can't go back to using the paint event because it doesn't solve my problem.

    Unless, of course I'm missing something blindingly obvious.

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

    Re: Stop graphics ellipse trail

    Quote Originally Posted by megamef View Post
    ...
    If I move the code back to the paint event then it strobes (as it does with the subroutine) but it only stays visible when I let go of the track bar sometimes.
    ....
    The only reason I can think that it would strobe is because you're still using CreateGraphics in the code when you move it to the paint event, rather than using the graphics object passed to you ( e.Graphics) in the paint event.

  10. #10
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Stop graphics ellipse trail

    Post the code that strobes and we can tell you why.

    passel is probably right, but I've consistently found when I try to guess what a user did, I end up making "bad guesses" and my code works, then it takes us a few extra hours to figure out how my code is different. I like to start with exactly your code because of that.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  11. #11

    Thread Starter
    Member
    Join Date
    Aug 2015
    Posts
    40

    Re: Stop graphics ellipse trail

    It's exactly the same code as in my sub routine, I've just copied and pasted it

  12. #12

    Thread Starter
    Member
    Join Date
    Aug 2015
    Posts
    40

    Re: Stop graphics ellipse trail

    OK! As I just posted that I copied and pasted the code I thought maybe because it's EXACTLY the same that is what the problem is so using passel's advice I changed:

    Code:
    Dim g As Graphics = PictureBox1.CreateGraphics
    to

    Code:
     
            Dim g As Graphics = e.Graphics
    Now it works.

    Now it all works, no strobing, leaves final image, no need for mouse up events to call the sub routine a final time.

    Thanks for all your help guys, I'll mark this as solved now.

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

    Re: Stop graphics ellipse trail

    We did mentioned that earlier, specifically mentioning using e.Graphics five days ago, but I guess sometimes it takes a while to make the connection about what drawing in the paint event means, i.e. using the provided graphics object.
    Quote Originally Posted by Sitten Spynne View Post
    ...
    So it turns out it is never right to use CreateGraphics() to draw at a random time. ...
    Quote Originally Posted by passel View Post
    ... you should either add the code from test to your paint event and using the e.Graphics object provided, or calling test() from your paint event, passing it the e.Graphics object provided by paint. That would eliminate strobing, trails and loss of ellipses on mouse up. ...

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