/Home /Archive /Syndicate /Blog /Support /About /Contact  
All Visual Basic Feeds in one place!





I’ve just changed my PC and while I was copying over some of the old stuff I found several projects I’d created to answer questions people had asked on VB City. So, before those projects get lost in the mist of time again, I thought I’d use some of them as blog topics, because these questions seem to come up time after time.  Here’s the first of them.

Display a random PictureBox

Someone had a group of PictureBoxes and wanted to display one at a time in a random sequence.  Let’s say that there are 9 PictureBoxes.  The first thing to do is to keep them under control and one way of doing that is to put them all in a Panel:

PictureBox1

There are various ways that you can identify the individual PictureBoxes at run time, but one of the easiest ways is to assign a value to the Tag property of each of them.  So each of the PictureBoxes you can see in that screenshot has an integer between 1 and 9 assigned to its Tag property.

At its most basic, all that’s needed is a timer to control the flow of PictureBox changes and code to select a random number between 1 and 9 to pick the next one to show. I used a Windows Forms Timer from the Toolbox and dragged it on to the form.  Here’s code that does that the random timing and display:

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Timer1.Enabled = True

        Timer1.Interval = 1000

    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick

        ' Create a random number variable

        Dim rnd As Random = New System.Random(Int(DateTime.Now.Millisecond))

        ' Assign the random number to an Integer variable

        Dim NextPic As Integer = rnd.Next(1, Panel1.Controls.Count + 1)

        ' Firstly, hide all picture boxes

        For Each pb As PictureBox In Panel1.Controls

            pb.Visible = False

        Next

        ' Then select one picturebox to display

        For Each pb As PictureBox In Panel1.Controls

            If CInt(pb.Tag) = NextPic Then pb.Visible = True

        Next

    End Sub

In the Form Load, I set the Timer running and set the interval between picture changes.  In the Timer’s Tick event, I first create a new Random object and then use the Next method of the Random class to limit the range of values between 1 and 9. I could have hard coded in that value of 9, because i know there are 9 picture boxes, but as a general rule it’s better to use code that calculates these kind of values.  That way, if you want to change the number of picture boxes or reuse the same code somewhere else, you can do that without changing the code.  When you hard code numbers, it’s really easy to forget you did so, and then after some changes you have to figure out why your code no longer works.  Those hard coded values are often the culprit.

The next step in the Tick event is to hide all the picture boxes.  Of course, once the application starts running there’ll only be one that’s visible, but this code is an easy way of hiding whichever one it is.  if you really wanted to identify the PictureBox that's currently visible you could of course do that, but with a simple app like this one, there’s not a lot of point.

Finally, the last For Each block of code checks through each of the PictureBoxes in turn and finds the one whose Tag property equals the currently selected random number.  That PictureBox is then displayed.  In this example, the PictureBox that has a Tag value of 2 is shown:

PictureBox2

That’s OK as far as it goes, but if the same number is chosen twice in succession – a very likely scenario with such a small range – the picture appears to flicker. What’s happening of course is that the display is cleared and then the same image is shown again.  This often won’t be acceptable, so we’d better code round that problem.

The first step is to create a variable that will keep track of the random number that was last selected (i.e. the Tag property of the currently visible PictureBox). 

   Dim lastPic As Integer = 0

Then, to make things easier to read, I’ll move the random generation code into a function of its own:

    Function GetRandomNumber() As Integer

        ' Create a random number variable

        Dim rnd As Random = New System.Random(Int(DateTime.Now.Millisecond))

        ' Assign the random number to an Integer variable

        Dim NextPic As Integer = rnd.Next(1, Panel1.Controls.Count + 1)

        ' Firstly, hide all pictureboxes

        For Each pb As PictureBox In Panel1.Controls

            pb.Visible = False

        Next

        Return NextPic

     End Function

Then create a function that checks if the random number that’s just been generated is a repeat.  If it is a repeat, then the value is changed.

    Function RepeatChecker(ByVal lastPicture As Integer, ByVal potentialPicture As Integer) As Integer

 

        If lastPicture <> potentialPicture Then

            Return potentialPicture

        ElseIf potentialPicture = Panel1.Controls.Count Then

            Return potentialPicture - 3

        Else : Return potentialPicture + 1

        End If

 

    End Function

The first ElseIf clause checks if the random value is (in this example that has 9 PictureBoxes) 9.  if it is, Then the value is manually changed to a lower value.  In this case, I’ve subtracted 3 from it, but I could have used any value under 9.

The final Else clause adds a value of 1 to the random number.  You’ll see now why I dealt with the value of 9 first.  If 1 is added to the total number of available picture boxes (in this case, making a figure of 10) and returned, an error will occur because (in this case) there isn’t a PictureBox that has 10 as its Tag property value.

Finally, the Tick event is changed so that these two functions are called:

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick

 

        Dim NextToDisplay As Integer = GetRandomNumber()

        NextToDisplay = RepeatChecker(lastPic, NextToDisplay)

 

        ' Then select one picturebox to display

        For Each pb As PictureBox In Panel1.Controls

            If CInt(pb.Tag) = NextToDisplay Then pb.Visible = True

        Next

 

        '  Note currently selected picturebox number

        lastPic = NextToDisplay

 

    End Sub

Notice that the last line of this event updates the lastPic variable with the value of the currently visible PictureBox.

© 2005 Serge Baranovsky. All rights reserved.
All feed content is property of original publisher. Designated trademarks and brands are the property of their respective owners.

This site is maintained by SubMain(), a division of vbCity.com, LLC