Go Back  Xtreme Visual Basic Talk > Visual Basic .NET (2002/2003/2005/2008, including Express editions) > .NET Interface and Graphics > Calling paint event


Reply
 
Thread Tools Display Modes
  #1  
Old 03-22-2012, 08:21 AM
george_m george_m is offline
Newcomer
 
Join Date: Mar 2012
Posts: 16
Default Calling paint event


This is a working example which draws a rectangle on different location every timer_tick and I fully understand now how it's working:

Code:
    Dim i, timercount As Integer

    Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
               e.Graphics.DrawRectangle(Pens.Purple, (50 + 2 * i), (50 + 2 * i), 30, 50)
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Timer1.Enabled = True
        Timer1.Start()
    End Sub

    Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        i = i + 1
        timercount = timercount + Timer1.Interval
        If timercount = 30 Then
            Timer1.Stop()
        End If

        PictureBox1.Refresh()
        
    End Sub
Now I'm looking for a way to draw this rectangles without refreshing them every single tick. I've just started using Visual Basic and I really don't know how to call/raise PictureBox1_Paint event every timer_tick or how to store drawing data in member variables and I would appreciate it to show me how to do this.
Reply With Quote
  #2  
Old 03-22-2012, 02:32 PM
passel's Avatar
passel passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 7,891
Default

I'm not quite following your questions.
You are causing the paint event every timer_tick now, until you stop the timer, so you know how to do that.
As for storing drawing data in members, there are endless possibilities.
I don't know of a lot of simple examples, off hand.
If you search for VB.Net GDI+ Tutorials, you will probably find more structured instruction than any examples we could point to, or want to explain in this thread.
I've been thinking and I don't think I want to attempt a mini-tutorial here.
Please search the internet for VB.Net GDI+ Tutorials, and try out some things and come back if you have specific questions with code you've written.
After you've worked through some tutorials, then you might be in a position to look at AtmaWeapon's example of updating a large number of graphics objects and possibly links posted in this thread in the Tech Discussions forum, which is a progression of different examples around the topic of using transforms.
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.
Reply With Quote
  #3  
Old 03-23-2012, 02:38 AM
george_m george_m is offline
Newcomer
 
Join Date: Mar 2012
Posts: 16
Default

To be more specific...
This program draws a rectangular let's say every second (depends on Timer's interval) on a different location in PictureBox1 and the total time is 30 seconds. After that time it stops drawing and on the PictureBox1 only one - the last of all rectangulars is seen. I'm searching a way to draw them all on the PictureBox1 without erasing them every Timer_Tick. At the end of that time I want all 30 rectangulars to be seen on the screen. The problem is in calling the Paint_Event but not using .Refresh() method in Timer_Tick event.
Reply With Quote
  #4  
Old 03-23-2012, 05:16 AM
DrPunk's Avatar
DrPunk DrPunk is offline
Senior Contributor

* Expert *
 
Join Date: Apr 2003
Location: Never where I want to be
Posts: 1,405
Default

One of DrawRectangles overloads lets you pass a rectangle object to the routine to draw the rectangle.

http://msdn.microsoft.com/en-us/library/sx8yykw8.aspx

The Rectangle class contains the location of the rectangle and the size of the rectangle.

http://msdn.microsoft.com/en-us/library/s21wk7kx.aspx

So there is already a class that will let you store drawing data, and then using that class for drawing is very simple indeed.

All that's left is someway of storing any number of those objects. Arrays or collections would do that job fine.

For simplicities sake, I'm going to use a collection
Code:
Dim Rectangulars as new collection ' I do like the word rectangulars.

' When you want to add a new rectangle that's going to be drawn, just add it to the collection of rectangles. It's up to you to determine the location and size of the rectangle
Rectangulars.Items.Add(New Rectangle(New Point(x, y), New Size(width, height))

' Then when you want to draw them all
dim rectangleToDraw as rect
For each rectangleToDraw in Rectangulars
    graphics.drawrectangle(pens.purple, rectangleToDraw)
Next
__________________
There are no computers in heaven!
Reply With Quote
  #5  
Old 03-25-2012, 10:35 AM
passel's Avatar
passel passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 7,891
Default

Another option is to simply use a persistent bitmap to hold your drawing and refresh the picturebox from there.
There are multiple ways to do that.
One is to simply set the picturebox image to your bitmap.
If you do that, then you draw on the bitmap and when you're done with an update simply trigger the paint event, and the Picturebox control will update the screen with its image, which is your bitmap, so you don't actually have to put code in the Paint Event since you're drawing to the bitmap in memory and will have the control update itself from that bitmap.
Also, this is like the Autodraw feature in VB6 and earlier, in that since the picturebox screen area is refreshed from the image, it won't be wiped out by a window being dragged across it.
Dragging a window across it will cause Paint Events, and the control will refresh the screen from the associated image.

So, your original code in Post 1 can be modified slightly.
Code:
Public Class Form1

  Dim i, timercount As Integer
  Dim persistentBmp As Bitmap

  Private Sub Button1_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Timer1.Enabled = True
    Timer1.Start()
  End Sub

  Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick
    i = i + 1
    timercount = timercount + Timer1.Interval
    If timercount = 30 Then
      Timer1.Stop()
    End If

    Dim g As Graphics = Graphics.FromImage(persistentBmp)              'Get a Graphics object for the bitmap
    g.DrawRectangle(Pens.Purple, (50 + 2 * i), (50 + 2 * i), 30, 50)   'Draw on the bitmap
    PictureBox1.Invalidate()                                           'Cause a paint event on the picturebox so it updates the screen from the image
    g.Dispose()                                                        'Dispose of the locally created graphics object
  End Sub

  Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    persistentBmp = New Bitmap(PictureBox1.ClientSize.Width, PictureBox1.ClientSize.Height)  'create a bitmap the same size as our PictureBox
    PictureBox1.Image = persistentBmp                                                        'Assign the bitmap to the picturebox so the screen will refresh from it
  End Sub
End Class
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.

Last edited by passel; 03-25-2012 at 10:45 AM.
Reply With Quote
  #6  
Old 03-26-2012, 03:44 AM
george_m george_m is offline
Newcomer
 
Join Date: Mar 2012
Posts: 16
Default

To DrPunk - I tryed to use a collection as you said like this:

Code:
   Dim i, timercount As Integer
Dim rectangulars as New Collection

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Timer1.Enabled = True
        Timer1.Start()
    End Sub

    Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        i = i + 1
        timercount = timercount + Timer1.Interval
        If timercount = 30 Then
            Timer1.Stop()
        End If

        rectangulars.Add(New Rectangle(New Point(((50 + 2 * i), (50 + 2 * i)), New Size(30, 50)))
        
    Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
         Dim rectangleToDraw as Rectangle
         For Each rectangleToDraw In rectangulars
             e.Graphics.DrawRectangle(Pens.Purple, rectangleToDraw)
         Next
    
    End Sub
but nothing appears in the PictureBox1 after the button click. Have I missed something?

To passel - I copyed your code but there's also something wrong. The only change is that button appears completely white on the screen and when I press it turns to a normal look and also nothing appears in the PictureBox1.
Reply With Quote
  #7  
Old 03-26-2012, 03:57 AM
DrPunk's Avatar
DrPunk DrPunk is offline
Senior Contributor

* Expert *
 
Join Date: Apr 2003
Location: Never where I want to be
Posts: 1,405
Default

If you put a debug breakpoint on the Picturebox1_Paint event you'll see that it only gets called when the form loads. Invalidating the picturebox in the timer will get the picturebox to call Paint.
__________________
There are no computers in heaven!
Reply With Quote
  #8  
Old 03-26-2012, 07:26 AM
george_m george_m is offline
Newcomer
 
Join Date: Mar 2012
Posts: 16
Default

Thanks a lot, works great now .
I also how to paint lines in similar way and I tryed to put information about points in a collection like this:

Code:
   Dim i, timercount As Integer
Dim points as New Collection

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Timer1.Enabled = True
        Timer1.Start()
    End Sub

    Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        i = i + 1
        timercount = timercount + Timer1.Interval
        If timercount = 30 Then
            Timer1.Stop()
        End If

        points.Add(New Point(50, 50))
        points.Add(New Point((50 + 2 * i), (50 + 2 * i)))

        PictureBox1.Invalidate()
        
    Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
         Dim lineToDraw as Point
         For Each lineToDraw In points
             e.Graphics.DrawLines(Pens.Purple, lineToDraw)
         Next
    
    End Sub
but there' s a problem in DrawLines order, because it's referring to a single point - it needs more than one to draw it.
Reply With Quote
  #9  
Old 03-26-2012, 07:31 AM
DrPunk's Avatar
DrPunk DrPunk is offline
Senior Contributor

* Expert *
 
Join Date: Apr 2003
Location: Never where I want to be
Posts: 1,405
Default

Yeah, lines require 2 points.

So you could create yourself a Line class that stores the two points and then you can store the lines in a collection.
Code:
Public Class Line
    Public Point1 as Point
    Public Point2 as Point

    Sub New(byval pnt1 as Point, byval pnt2 as Point)
        me.Point1 = pnt1
        me.Point2 = pnt2
    End Sub
End Class

dim lines as new collection

lines.Add(New Line(New Point(x1, y1), New Point(x2, y2)))

dim l as Line
For Each l In lines
    e.Graphics.DrawLines(Pens.Purple, l.Point1, l.Point2)
Next
__________________
There are no computers in heaven!
Reply With Quote
  #10  
Old 03-26-2012, 01:57 PM
passel's Avatar
passel passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 7,891
Default

Quote:
Originally Posted by george_m View Post
...To passel - I copyed your code but there's also something wrong. The only change is that button appears completely white on the screen and when I press it turns to a normal look and also nothing appears in the PictureBox1.
Well, I don't know. It seemed pretty straight forward.
I tested it with VB.net 2010 originally. Just now, I tried it again in VB.net 2005.
Simply created a new project.
Added a button, picturebox and timer control.
Pasted the code from the post into the project and ran it.
It worked fine for me.
I'll post the project and you can try it directly, without having to create a project and paste the code in.
Attached will be a 2005 project, so if you're using 2008 or 2010 it should automatically offer to upgrade the project to what you're using.
Attached Files
File Type: zip PersistentPictureboxExample.zip (15.3 KB, 14 views)
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Forum Jump

Advertisement:





Free Publications
The ASP.NET 2.0 Anthology
101 Essential Tips, Tricks & Hacks - Free 156 Page Preview. Learn the most practical features and best approaches for ASP.NET.
subscribe
Programmers Heaven C# School Book -Free 338 Page eBook
The Programmers Heaven C# School book covers the .NET framework and the C# language.
subscribe
Build Your Own ASP.NET 3.5 Web Site Using C# & VB, 3rd Edition - Free 219 Page Preview!
This comprehensive step-by-step guide will help get your database-driven ASP.NET web site up and running in no time..
subscribe
 
 
-->