简体   繁体   English

重新绘制方法无法及时工作

[英]Repaint method isn't working in time

I'm making a game in Java, and the repaint() method is misbehaving in a very odd way. 我正在用Java开发游戏,并且repaint()方法的行为异常。 Basically, I need to repaint the board before getting the AI's move. 基本上,我需要在重新获得AI之前重新粉刷电路板。 Here is my method where I'm calling it: 这是我调用的方法:

public void mouseClicked(MouseEvent e) {
    mouseX = e.getX();
    mouseY = e.getY();

    int button = e.getButton();
    if (button == MouseEvent.BUTTON1 || button == MouseEvent.BUTTON3) {
        int mouseR = (mouseY / SIZE);
        int mouseC = (mouseX / SIZE);

        if (mouseR >= 0 && mouseC >= 0 &&
                mouseR < board.length && mouseC < board[0].length) {
            if (board[mouseR][mouseC] == 3) {
                makeMove(mouseR, mouseC, playerColor);
                getValidMoves((playerColor % 2) + 1);
                repaint();
                getAIMove();
            }
        }

    }
    repaint();
}

getAIMove() is designed so it waits for a couple of seconds before making the move, so the player can see the results of their move before they see those of the AI. getAIMove()的设计使其在移动之前要等待几秒钟,以便玩家在看到AI之前就可以看到其移动的结果。 Unfortunately, although I call repaint() before getAIMove() , what happens is more like this: the player clicks where they want to move. 不幸的是,尽管我在getAIMove() repaint()之前调用repaint() ,但发生的情况更像是这样:玩家单击了他们想要移动的位置。 Nothing appears to happen for a few seconds, then the results of the player's move AND the AI's move are displayed on the screen. 几秒钟似乎什么都没发生,然后在屏幕上显示玩家移动和AI移动的结果。 What's going on? 这是怎么回事?

All the code in your mouseClicked() event handler will run on the special AWT/Swing Thread. mouseClicked()事件处理程序中的所有代码都将在特殊的AWT / Swing线程上运行。

repaint() does not repaint the GUI immediately - it schedules a repaint , (see this article ) which will also run on the Swing thread - but not until your event handler has finished - the Swing thread can only do one thing at a time! repaint()不会立即重新绘制GUI-它调度一个repaint (请参阅本文 ),该操作也将在Swing线程上运行-但直到事件处理程序完成时-Swing线程一次只能做一件事!

So you won't see the results of getAIMove() until afterwards. 因此,直到之后您才能看到getAIMove()的结果。

You probably need to run the getAIMove() logic in a separate background thread, then update the GUI (which must be done in the Swing thread, using SwingUtilities.invokeLater() or the SwingWorker helper class.) 您可能需要在单独的后台线程中运行getAIMove()逻辑,然后更新GUI(必须使用SwingUtilities.invokeLater()SwingWorker帮助器类在Swing线程中完成SwingUtilities.invokeLater()

Or, you could schedule the AI to run on the Swing thread, using invokeLater() - it will then run after the first repaint() . 或者,您可以使用invokeLater()安排AI在Swing线程上运行-然后,它将在第一个repaint()之后运行。 However, this method is undesirable (unless the AI is very fast), because your GUI will be unresponsive until the Swing thread becomes free again to handle repaints. 但是,此方法是不可取的(除非AI非常快),因为在Swing线程再次变得可以自由处理重绘之前,您的GUI将无响应。

See also the Java tutorials on these topics: 另请参阅关于这些主题的Java教程:

A friend and I figured out a little trick to beat the queue described by @DNA - here's my new code: 我和一个朋友想出了一个小技巧来克服@DNA描述的队列-这是我的新代码:

public void mousePressed( MouseEvent e )
   {
      mouseX = e.getX();
      mouseY = e.getY();

      int button = e.getButton();
      if(button == MouseEvent.BUTTON1 || button == MouseEvent.BUTTON3)
      {
         int mouseR = (mouseY/SIZE);
         int mouseC = (mouseX/SIZE);

         if(mouseR >=0 && mouseC >= 0 && mouseR < board.length && mouseC < board[0].length)
         {
            if (board[mouseR][mouseC] == 3){
               makeMove(mouseR, mouseC, playerColor);
            }
         }

      } 
      repaint();
   }

   public void mouseReleased( MouseEvent e )
   {
      int button = e.getButton();
      if(button == MouseEvent.BUTTON1 || button == MouseEvent.BUTTON3)
      {
         int mouseR = (mouseY/SIZE);
         int mouseC = (mouseX/SIZE);

         if(mouseR >=0 && mouseC >= 0 && mouseR < board.length && mouseC < board[0].length)
         {
            if (board[mouseR][mouseC] == playerColor){
               getValidMoves((playerColor % 2) + 1);
               getAIMove();
               getValidMoves(playerColor);
            }
         }

      } 
      repaint();
   }

By doing the player's move when the mouse is pressed, and waiting to do the AI's move until the mouse is released, the program is allowed to complete the Swing thread and repaint the board. 通过在按下鼠标时执行玩家的移动,并等待AI的移动直到释放鼠标,程序才能完成Swing线程并重新粉刷电路板。 Thanks for all of your help! 感谢您所有的帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM