Swing Countdown from 5 to 0

三世轮回 提交于 2019-12-24 06:35:21

问题


I am creating a Java Swing game and before every new game I would like to have a frame show up and countdown from 5 to 0 seconds.

While this is happening I would like the game in the background to wait until the countdown is complete. What would be the best way to make the game in the background wait?

I have tried Thread.sleep but this causes the The Event Dispatch Thread to sleep and the GUI not to update. However, it works the first time i run it but not the second.

Thankful for your help.

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

Solution

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

回答1:


Don't use a JFrame, use some kind of modal dialog

Take a look at How to Make Dialogs for more details




回答2:


Seems that you want something like a SplashScreen. Have you looked to the SplasScreen Tutorial from Oracle? There Thread.sleep() is used safely and it updates the graphics correctly. I think it to be your unique solution. The only way to let the undergoing application to wait is to use the same thread. The reason your Timer didn't work is because it creates another thread to run itself.




回答3:


Another option is to use a 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();
    }
  }
}


来源:https://stackoverflow.com/questions/24200634/swing-countdown-from-5-to-0

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!