0

我正在尝试创建一个倒计时,其中显示文本“GAME STARTS IN:”并使用 for 循环和 Thread.Sleep 变量从三个倒计时。我首先使用设计器创建“游戏开始于:”部分,但在变量不显示后,我将其移至代码中。现在什么都没有出现。这就是我现在的计时器方法中的内容:
if (!countedDown)
DoCountdown();

Countdown.Hide();

然后在 DoCountdown 方法中:

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);
 }

我在 System.Threading.Thread.Sleep(100) 处设置了一个断点,一切看起来都很正常。Countdown.Text 等于“GAME STARTS IN: 3”。尝试集成解决方案后,文本未显示。这是我的代码中的更多上下文:

这是我的开始屏幕表格

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

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

3 回答 3

1

试试下面的东西。按钮用于启动计时器并设置初始值。

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");
  }
}

根据 OP 评论进行编辑。

在开始屏幕表单中尝试这样的代码......

private void StartMultiplayerGame(object sender, EventArgs e) {
  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";
    GameScreen startGame = new GameScreen();
    startGame.Show();
    this.Hide();
  }
}
于 2021-08-04T08:24:36.983 回答
0

循环阻塞主线程以刷新 UI,因此可以通过将循环移动到单独的方法来存档所需的场景

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

创建启动此方法的新线程

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

并且由于需要在另一个线程中更新 UI 并使其安全地将 setText 分隔在一个单独的方法中,该方法基于调用属性所需的检查进行更新,这将使其在所有情况下都有效

 void setCountDownText(string txtValue)
        {
            if (Countdown.InvokeRequired)
            {
                Action safeWrite = delegate { setCountDownText(txtValue); };
                Countdown.Invoke(safeWrite);
            }
            else
                Countdown.Text = txtValue;
        } 
于 2021-08-04T08:32:15.620 回答
0

执行此操作的“现代”方法是使用 async/await。

例如,从按钮处理程序启动 DoCountdown() 可能如下所示:

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);
    }
}

但是,任何调用DoCountdown()都需要声明为async,等等调用树。

async void请注意,除了作为异步方法的返回类型之外,唯一可接受的地方async Task是该方法是事件处理程序,例如上面示例中的按钮处理程序。

于 2021-08-04T08:34:18.117 回答