java - 在 Java 纸牌游戏中,我如何在每张牌发到手后短暂暂停?

标签 java user-interface sleep wait

我正在使用 netbeans 中的 swing 在 java 中创建一个二十一点游戏。牌按顺序发给玩家的多手牌和庄家。当发完每张牌时,带有牌图像的 JLabels 会出现在 jLayerdPanes 中。我想在每张牌发完后暂停一下。目前你只能看到它们全部被同时处理。这是发出的前四张牌的代码。

    if(hand1.handIsInPlay()==true){
       dealCard(jLPaneHand1,hand1);
       pause();
    }
    if(hand2.handIsInPlay()==true){
       dealCard(jLPaneHand2,hand2);
       pause();
    }
    if(hand3.handIsInPlay()==true){
       dealCard(jLPaneHand3,hand3);
       pause();
    }
    dealCard(jLPaneDealerHand,dealerHand);

这是我尝试过的暂停方法:

public void pause(){
    try {
      Thread.sleep(1000);
    } 
    catch(InterruptedException ex) {
        Thread.currentThread().interrupt();
    }
}

这是我尝试过的第二种暂停方法:

public void pause(){
    try {
        TimeUnit.MILLISECONDS.sleep(1000);
    } 
    catch (InterruptedException e) {
        //Handle exception
    }
}

都没有按预期工作。看起来发生的情况是,如果进行三手牌,则程序会汇总 3x1000ms 并等待该长度,然后立即发所有牌。

如何让程序在每张牌发完后暂停?

最佳答案

您需要记住 Thread.sleep 是在当前线程中调用的。在带有 Swing 的 Java 中,通常至少有 2 个线程 - 主线程和 Swing 线程 - 当您触发一个操作时,会调用适当的监听器并执行它的方法 - 只要该方法仍在运行,它就无法继续执行其他任务,例如。例如重新绘制卡片。

所以基本上你需要将此暂停操作移动到其他线程,该线程将使用例如绘制卡片的操作来排序SwingUtilities.invokeLater,然后等待一段时间,然后再次命令重绘等等。

基本上,您需要确保 GUI 线程不被阻塞并且可以一直工作,并且订单来自其他一些线程 - 并且它们可以 hibernate 而不打扰用户。

在您的情况下,所有事情都发生在 1 个线程中,因此当您调用 sleep 时,GUI 线程会 hibernate 并且无法执行任何操作,例如绘制您想要绘制的内容 - 它会耐心等待,直到您在 Swing 线程中的代码停止执行。

编辑:

简单示例 - 了解确切的要求和代码将使其表现得更好......

在监听器调用中,例如:

new Thread(new CardDealing()).start(); // delegates task to the new thread

虽然任务看起来像:

public CardDealing extends Runnable {
    // inner data, methods and so on

    public void run() {
        if(hand1.handIsInPlay()==true){
            dealCard(jLPaneHand1,hand1);
            pause();
        }
        if(hand2.handIsInPlay()==true){
            dealCard(jLPaneHand2,hand2);
            pause();
        }
        if(hand3.handIsInPlay()==true){
            dealCard(jLPaneHand3,hand3);
            pause();
        }
        dealCard(jLPaneDealerHand,dealerHand);
    }

    public void dealCards(...) {
         // this part will be run in a non-gui thread - make sure that
         // all calculations and changes in model are made here
         SwingUtilities.invokeLater(new Runnable() {
             public void run() {
                 // this will be run in a swing thread
                 // - make sure that only code dealing directly
                 // with GUI is called here
                 guiDealCards(jPane,hand);
             }
         });
    }
}

当然,根据您的要求,CardDealing 类可能会采用参数、包含对某些数据的引用等 - 但这是整体设计的问题。 GUI 和工作线程之间的通信应该或多或少像这样工作。在这种特殊情况下,您也可以尝试 invokeAndWait - 只需确保 pause() 不在 GUI 线程内调用(自定义 Swing 组件、Runnables您委托(delegate)的、paint 方法等)。

编辑2:

您可能会发现this link有帮助 - 它将帮助您理解 Swing 的工作原理,以及为什么您应该将逻辑至少分为 2 个部分:GUI 和非 GUI。然后不管怎样 与dealCards方法中直接的GUI位置无关,而guiDealCards中所有与GUI相关的内容 - 我不知道你到底在那里做什么,所以我不能告诉你为你。

关于java - 在 Java 纸牌游戏中,我如何在每张牌发到手后短暂暂停?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23175676/

相关文章:

java - 程序终止而不在 Eclipse 中运行

java - GUI ImageIcon 一副牌

iphone - 在 sleep 模式下与 iPhone 交互

java - Java Web 应用程序的电子邮件服务器功能

java - 将 GWTquery 与 GWT 结合使用

用于 GUI 的 Java 2D 场景图形库

user-interface - 如何使用 Xamarin.Forms 同时在一个屏幕上创建具有多个 ContentPages 的平板电脑 UI?

java - 需要一个定时的 panel.repaint();

c++ - std::this_thread::sleep_for() 可以有虚假唤醒吗?

java - super 开发模式 + Tomcat 中的 JSP 页面