【问题标题】:Swing Countdown from 5 to 0从 5 到 0 的摇摆倒计时
【发布时间】:2014-06-13 08:11:57
【问题描述】:

我正在创建一个 Java Swing 游戏,并且在每个新游戏之前,我都希望有一个帧显示和从 5 秒到 0 秒的倒计时。

在发生这种情况时,我希望后台游戏等到倒计时完成。让游戏在后台等待的最佳方法是什么?

我已经尝试过 Thread.sleep 但这会导致事件调度线程进入睡眠状态并且 GUI 不会更新。但是,它在我第一次运行时有效,但在第二次时无效。

感谢您的帮助。

public class CountdownPresenterPanel {
    JFrame mainFrame;
    int currentNumber = 5;
    JLabel textLabel;

    CountdownPresenterPanel() {
        mainFrame = new JFrame();
        textLabel = new JLabel(String.valueOf(currentNumber), SwingConstants.CENTER);
        textLabel.setFont(new Font("Arial", Font.BOLD, 55));
        textLabel.setVerticalAlignment(SwingConstants.CENTER);
        mainFrame.add(textLabel);
        mainFrame.setUndecorated(true); // Remove bar including close, minimize
        mainFrame.setSize(600,300);
        mainFrame.setLocationRelativeTo(null);
        mainFrame.setVisible(true);
        Timer timer = new Timer(1000, new ActionListener() { 
            @Override
            public void actionPerformed(ActionEvent e) {
                if(currentNumber > 0) {
                    currentNumber--;
                    textLabel.setText(String.valueOf(currentNumber));
                } else {
                    mainFrame.setVisible(false);
                    mainFrame.dispose();
                }
            }
        });
        timer.setRepeats(true);
        timer.start();
    }
}

解决方案

import java.awt.*;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.Timer;

public class CountdownPresenterPanel {
    private int currentNumber = 5;
    private JLabel textLabel;
    private final JDialog dialog;
    CountdownPresenterPanel() {
        Timer timer = new Timer(1000, new ActionListener() { 
            @Override
            public void actionPerformed(ActionEvent e) {
                if(currentNumber > 0) {
                    currentNumber--;
                    textLabel.setText(String.valueOf(currentNumber));
                } else {
                    dialog.dispose();
                }
            }
        });
        Frame window = new Frame();
        dialog = new JDialog(window, "Alert", true);
        textLabel = new JLabel(String.valueOf(currentNumber), SwingConstants.CENTER);
        textLabel.setFont(new Font("Arial", Font.BOLD, 55)); // Increase the font-size
        dialog.add(textLabel);
        dialog.setSize(400, 200);
        dialog.setLocationRelativeTo(null);
        timer.setRepeats(true);
        timer.start();
        dialog.setUndecorated(true);
        dialog.setVisible(true);
    }
}

【问题讨论】:

    标签: java swing countdown


    【解决方案1】:

    不要使用JFrame,使用某种模式对话框

    查看How to Make Dialogs了解更多详情

    【讨论】:

    • 模式对话框不足以导致在另一个线程中运行的游戏等待,不是吗?
    • 对话框会改变@MadProgrammer 的什么? EDT 我不会有同样的问题吗?
    • 不,这就是模态对话框的用途。至于你的线程,你可以使用暂停标志和对象监视器来暂停它
    • 就像任何其他窗口一样,处理
    • 模式对话框被阻塞,它会阻止用户选择应用程序中的任何其他窗口,它会在对话框可见时停止代码执行,我的意思是你不需要一些精心设置的侦听器以了解对话框何时关闭;)
    【解决方案2】:

    您似乎想要SplashScreen之类的东西。你看过SplasScreen Tutorial from Oracle? 那里Thread.sleep() 是安全使用的,它会正确更新图形。我认为这是您独特的解决方案。让正在进行的应用程序等待的唯一方法是使用相同的线程。您的 Timer 不起作用的原因是它创建了另一个线程来运行自己。

    【讨论】:

      【解决方案3】:

      另一种选择是使用SwingWorker

      import java.awt.*;
      import java.util.List;
      import java.util.concurrent.ExecutionException;
      import java.beans.*;
      import javax.swing.*;
      
      public class CountdownPresenterPanel2 {
        public static void main(String[] args) {
          final JFrame frame = new JFrame();
          final JDialog splashScreen = new JDialog(null, Dialog.ModalityType.DOCUMENT_MODAL);
          final JLabel textLabel = new JLabel(String.valueOf(5), SwingConstants.CENTER);
      
          EventQueue.invokeLater(new Runnable() {
            @Override public void run() {
              textLabel.setFont(new Font("Arial", Font.BOLD, 55));
              textLabel.setVerticalAlignment(SwingConstants.CENTER);
              splashScreen.setUndecorated(true);
              splashScreen.getContentPane().add(textLabel);
              splashScreen.setSize(600, 300);
              splashScreen.setLocationRelativeTo(null);
              splashScreen.setVisible(true);
            }
          });
          (new GamePanelInitTask() {
            @Override protected void process(java.util.List<Integer> chunks) {
              for (Integer value : chunks) {
                textLabel.setText(value.toString());
              }
            }
            @Override public void done() {
              splashScreen.dispose();
              try {
                MainGamePanel p = get();
                frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
                frame.getContentPane().add(p);
                frame.setSize(320, 240);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
              } catch (InterruptedException | ExecutionException ex) {
                ex.printStackTrace();
              }
            }
          }).execute();
        }
      }
      
      class GamePanelInitTask extends SwingWorker<MainGamePanel, Integer> {
        @Override public MainGamePanel doInBackground() {
          int currentNumber = 5;
          MainGamePanel game = new MainGamePanel();
          while (currentNumber > 0 && !isCancelled()) {
            currentNumber--;
            publish(currentNumber);
            game.add(new JLabel(String.format("Label: %d", currentNumber)));
            try {
              Thread.sleep(1000); //dummy task
            } catch (InterruptedException ie) {
              ie.printStackTrace();
              return null;
            }
          }
          return game;
        }
      }
      
      class MainGamePanel extends JPanel {
        public MainGamePanel() {
          super();
          try {
            Thread.sleep(1000); //dummy task
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多