WinFormsC#仅在通过计时器的每个其他循环上更新PictureBoxes

问题描述

我正在使用C#中的WinForms制作视频扑克风格的街机游戏。当玩家单击“交易”按钮时,表格上的5个图片框将从正面朝下的卡片图像切换为正面朝上的卡片图像。我毫不费力地让它们一次翻转,但我希望每张卡之间都稍有延迟,以便它们从左向右显示

我从Microsoft .NET官方文档中找到了一个示例(this page上的第二个示例),该示例使用Timer的方式仅会循环设置一定的次数,这对我来说很完美,因为我只是想翻转5张卡片。

当我在游戏中使用该示例时,会发生一些奇怪的事情。卡片从左到右成对显示两次,而不是一次显示。当我设置一个断点并逐步通过时,我的计数器确实在增加一,但是该表格仅每隔一遍更新一次图像。

为什么会这样?而我该怎么办呢?

交易按钮单击:

private void dealdraw_button1_Click(object sender,EventArgs e)
{
  // If we are dealing a new hand...
  if (dealPhase == "deal")
  {
    // Change game phase
    dealPhase = "draw";

    // Generate a new deck of cards
    deck = new Deck();

    // Shuffle the deck
    deck.Shuffle();

    // Deal five cards to the player
    playerHand = deck.DealHand();

    // Start timer loop
    InitializeTimer();

    // Enable "Hold" buttons
    for (int i = 0; i < 5; i++)
    {
      playerHoldButtons[i].Enabled = true;
    }
  }
}

InitializeTimer():

private void InitializeTimer()
{
  counter = 0;
  timer1.Interval = 50;
  timer1.Enabled = true;
  // Hook up timer's tick event handler.  
  this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
}

Timer1_Tick:

private void timer1_Tick(object sender,EventArgs e)
{
  if(counter >= 5)
  {
    // Exit loop code
    timer1.Enabled = false;
    counter = 0;
  }
  else
  {
    playerHandPictureBoxes[counter].Image = cardFaces_imageList1.Images[playerHand[counter].imageListIndex];
    counter = counter + 1;
  }
}

解决方法

我认为您希望Invalidate方法导致发生Repaint事件:

playerHandPictureBoxes[counter].Image = cardFaces_imageList1.Images[playerHand[counter].imageListIndex];
playerHandPictureBoxes[counter].Invalidate();

参考:https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.control.update?view=netcore-3.1#System_Windows_Forms_Control_Update

有两种方法可以重绘表单及其内容:

  • 您可以将Invalidate方法的重载之一与Update方法一起使用。
  • 您可以调用Refresh方法,该方法强制控件重绘自身及其所有子级。这等效于将Invalidate方法设置为true并将其与Update一起使用。

Invalidate方法控制要绘制或重新绘制的内容。 Update方法控制何时进行绘制或重新绘制。如果您一起使用Invalidate和Update方法而不是调用Refresh,则重新绘制的内容取决于您使用的Invalidate重载。 Update方法只是强制立即绘制控件,而Invalidate方法则控制调用Update方法时绘制的内容。

您可能想增加“计时器间隔”或计数器,250毫秒对于观看动画来说有点快/短。

,

InitializeTimer方法中的问题。罪魁祸首是您在每次点击中一次又一次地添加Tick事件处理程序。

df.DOB <- c("12/11/99","10/24/67","07/25/1923","01/07/1989","09/02/1974","01/19/1987")

sub("19(..)$","\\1",df.DOB)

# [1] "12/11/99" "10/24/67" "07/25/23" "01/07/89" "09/02/74" "01/19/87"
,

我想将此添加为评论,但是我的声誉不允许这样做。

设置图像后,您可以尝试playerHandPictureBoxes[counter].Image.Update();。尚未测试过。