Search code examples
vb.netwinformsbackcolor

How can I get the backcolor of a button to change colour if it contains the correct answer? Visual Basic 2010


I have created a multiple choice quiz, but am struggling with coming up with the correct code to make it so that if the player selects the button containing the correct answer, its BackColor will turn green for a few seconds, before the next question appears automatically and returns to its normal BackColor.

Also, if the player selects the button containing the wrong answer, then its BackColor turns red to establish to the player that they were incorrect.

For this, I have a label called lblQuestion, which contains the question being asked and then four buttons (btnAnswerA, btnAnswerB, btnAnswerC and btnAnswerD) which all contain a potential answer to the question, with of course, only one being correct.

I have been fiddling around with the code for sometime, trying to get it to work, but it doesn't work how I want to, so thought to come on here for some guidance in this matter.

Below is some of the code relating to this issue. I am sure by looking at it, many of you will know where I am going wrong!

Private Sub btnAnswerA_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAnswerA.Click

    If strAnswer = "A" Then
        btnAnswerA.BackColor = Color.Green
        intScore = intScore + 100
        lblScore.Text = intScore
    Else
        btnAnswerA.BackColor = Color.Red
        Call GetQuestion(questionNumber)
    End If

    Call GetQuestion(questionNumber)
    prgbarOne.Value = 0

End Sub

Private Sub btnAnswerB_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAnswerB.Click

    If strAnswer = "B" Then
        btnAnswerB.BackColor = Color.Green
        intScore = intScore + 100
        lblScore.Text = intScore
    Else
        btnAnswerB.BackColor = Color.Red
        Call GetQuestion(questionNumber)
    End If

    Call GetQuestion(questionNumber)
    prgbarOne.Value = 0

End Sub

Private Sub btnAnswerC_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAnswerC.Click

    If strAnswer = "C" Then
        btnAnswerC.BackColor = Color.Green
        intScore = intScore + 100
        lblScore.Text = intScore
    Else
        btnAnswerC.BackColor = Color.Red
        Call GetQuestion(questionNumber)
    End If

    Call GetQuestion(questionNumber)
    prgbarOne.Value = 0

End Sub

Private Sub btnAnswerD_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAnswerD.Click

    If strAnswer = "D" Then
        btnAnswerD.BackColor = Color.Green
        intScore = intScore + 100
        lblScore.Text = intScore
    Else
        btnAnswerD.BackColor = Color.Red
        Call GetQuestion(questionNumber)
    End If

    Call GetQuestion(questionNumber)
    prgbarOne.Value = 0

End Sub

Basically, I just need some help with knowing how to get the BackColor to turn green/red (depending on whether they're right or wrong) for a few moments before showing the next question where Call GetQuestion(questionNumber) is and knowing how to get the original BackColor (which is Gray) to return for the next question before the player has clicked on a button.

Hope this makes sense and any help is really appreciated. I apologise, I am still new to programming (as you may tell). Also, if more code is needed, I will submit it.


Solution

  • As APrough has pointed out, you can use the Thread.Sleep Method right before each of your Call GetQuestion(questionNumber).

    You can adjust the millisecondsTimeout parameter that represents the number of milliseconds for which the thread is blocked. For example to sleep for 2 seconds:

    System.Threading.Thread.CurrentThread.Sleep(2000)
    

    But,

    I did try that, but what happens is that it freezes without changing the button colour to green/red whilst the question is shown in the label, so ends up delaying onto the next question where new answers are shown.

    The reason of that behavior is explained on MSDN about the Application.DoEvents method, that is also the solution:

    If you call DoEvents in your code, your application can handle the other events. For example, if you have a form that adds data to a ListBox and add DoEvents to your code, your form repaints when another window is dragged over it. If you remove DoEvents from your code, your form will not repaint until the click event handler of the button is finished executing.

    It's what happen for you, the backcolor is not refreshed because I guess you reset the backcolor in the GetQuestion method. So what you need is to call this method (Application.DoEvents) before the Thread.Sleep method.

    Your code would be:

    Private Sub btnAnswerA_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAnswerA.Click
    
        If strAnswer = "A" Then
            btnAnswerA.BackColor = Color.Green
            intScore = intScore + 100
            lblScore.Text = intScore
        Else
            btnAnswerA.BackColor = Color.Red
            'Call GetQuestion(questionNumber) no need here, it will be called after
        End If
    
       'Make sure backcolor is refreshed
        Application.DoEvents()
    
        'Wait for two second
        System.Threading.Thread.Sleep(2000)
    
        Call GetQuestion(questionNumber)
        prgbarOne.Value = 0
    
    End Sub
    
    Private Sub btnAnswerB_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAnswerB.Click
    
        If strAnswer = "B" Then
            btnAnswerB.BackColor = Color.Green
            intScore = intScore + 100
            lblScore.Text = intScore
        Else
            btnAnswerB.BackColor = Color.Red
            'Call GetQuestion(questionNumber) no need here, it will be called after
        End If
    
        'Make sure backcolor is refreshed
        Application.DoEvents()
    
        'Wait for two second
        System.Threading.Thread.Sleep(2000)
    
        Call GetQuestion(questionNumber)
        prgbarOne.Value = 0
    
    End Sub
    
    Private Sub btnAnswerC_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAnswerC.Click
    
        If strAnswer = "C" Then
            btnAnswerC.BackColor = Color.Green
            intScore = intScore + 100
            lblScore.Text = intScore
        Else
            btnAnswerC.BackColor = Color.Red
            'Call GetQuestion(questionNumber) no need here, it will be called after
        End If
    
        'Make sure backcolor is refreshed
        Application.DoEvents()
    
        'Wait for two second
        System.Threading.Thread.Sleep(2000)
    
        Call GetQuestion(questionNumber)
        prgbarOne.Value = 0
    
    End Sub
    
    Private Sub btnAnswerD_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAnswerD.Click
    
        If strAnswer = "D" Then
            btnAnswerD.BackColor = Color.Green
            intScore = intScore + 100
            lblScore.Text = intScore
        Else
            btnAnswerD.BackColor = Color.Red
            'Call GetQuestion(questionNumber) no need here, it will be called after
        End If
    
        'Make sure backcolor is refreshed
        Application.DoEvents()
    
        'Wait for two second
        System.Threading.Thread.Sleep(2000)
    
        Call GetQuestion(questionNumber)
        prgbarOne.Value = 0
    
    End Sub