ineedhelp
ineedhelp

Reputation: 11

Why is the text not showing up on screen?

I'm trying to create a countdown where the text displays, "GAME STARTS IN: " and using a for loop and Thread.Sleep a variable counts down from three. I started by using the designer to create the "game starts in:" part, but after the variable wouldn't show up I moved it to code. Now nothing shows up. This is what I have now in my timer method:
if (!countedDown)
DoCountdown();

Countdown.Hide();

And then in a DoCountdown method:

this.Countdown.BackColor = System.Drawing.Color.Transparent;                                                               
this.Countdown.ForeColor = System.Drawing.Color.White;
this.Countdown.Location = new System.Drawing.Point(360, 17);
this.Countdown.Name = "Countdown";
this.Countdown.Font = new System.Drawing.Font("Segoe UI", 12F, 
System.Drawing.FontStyle.Regular, 
System.Drawing.GraphicsUnit.Point);
this.Countdown.Size = new System.Drawing.Size(185, 24);
this.Countdown.TabIndex = 6;
                       
 countedDown = true;
 for (int i = 3; i > 0; i--)
 {
    Countdown.Text = "GAME STARTS IN: " + i;
    System.Threading.Thread.Sleep(1000);
 }

I put a breakpoint at System.Threading.Thread.Sleep(100) and everything seemed normal. Countdown.Text was equal to "GAME STARTS IN: 3". After trying to integrate the solutions the text doesn't show up. Here is some more context in my code:

This is from my start screen form

   private void QuitGame(object sender, EventArgs e)
   {
      Application.Exit();
   }

    private void StartMultiplayerGame(object sender, EventArgs e)
    {
        GameScreen startGame = new GameScreen();
        startGame.Show();
        Hide();
    }

Upvotes: 0

Views: 237

Answers (3)

JohnG
JohnG

Reputation: 9479

Try something like below. A button is used to start the timer and set the initial values.

int count = 3;
private void button2_Click(object sender, EventArgs e) {
  timer1.Interval = 1000;
  count = 3;
  label1.Text = "GAME STARTS IN: " + count;
  timer1.Start();
}

private void timer1_Tick(object sender, EventArgs e) {
  count--;
  if (count != 0) {
    label1.Text = "GAME STARTS IN: " + count;
  }
  else {
    timer1.Stop();
    label1.Text = "GAME STARTED";
    MessageBox.Show(" -> GO");
  }
}

Edit per OP comments.

Try the code like this in the start screen form...

private void StartMultiplayerGame(object sender, EventArgs e) {
  count = 3;
  label1.Text = "GAME STARTS IN: " + count;
  timer1.Start();
}

Then change the timer code to...

private void timer1_Tick(object sender, EventArgs e) {
  count--;
  if (count != 0) {
     label1.Text = "GAME STARTS IN: " + count;;
  }
  else {
    timer1.Stop();
    label1.Text = "Game Started";
    GameScreen startGame = new GameScreen();
    startGame.Show();
    this.Hide();
  }
}

Upvotes: 1

Matthew Watson
Matthew Watson

Reputation: 109762

The "modern" way to do this is using async/await.

For example, launching the DoCountdown() from a button handler could look like this:

async void testBtn_Click(object sender, EventArgs e)
{
    await DoCountdown();
}

async Task DoCountdown()
{
    // <Initialisation of Countdown elided for brevity>

    for (int i = 3; i > 0; i--)
    {
        Countdown.Text = "GAME STARTS IN: " + i;
        await Task.Delay(1000);
    }
}

However, whatever calls DoCountdown() will need to be declared as async, and so on up the call tree.

Note that the only acceptable place to have async void rather than async Task as a return type for an async method is where the method is an event handler such as the button handler in the example above.

Upvotes: 0

MHassan
MHassan

Reputation: 435

loop blocking the main thread to refresh UI so the required scenario can be archived by moving the loop to a separate method

void doCountDown()
        {
            for (int i = 10; i > 0; i--)
            {
                setCountDownText( "GAME STARTS IN: " + i);
                System.Threading.Thread.Sleep(1000);
            }
        }

creating anew thread that start this method

 new System.Threading.Thread(new System.Threading.ThreadStart(doCountDown)).Start();

and because of the need to update UI in another thread and to make it safe separate the setText in a separate method that update based on checking required to invoke property this will make it work in all cases

 void setCountDownText(string txtValue)
        {
            if (Countdown.InvokeRequired)
            {
                Action safeWrite = delegate { setCountDownText(txtValue); };
                Countdown.Invoke(safeWrite);
            }
            else
                Countdown.Text = txtValue;
        } 

Upvotes: 0

Related Questions