我正在尝试在Applet中开发游戏,我遇到了这个问题。我希望显示器在游戏继续之前向用户显示倒计时。但是,倒计时不会显示,实际上会使GUI冻结。如何避免这种情况?以下是一些证明此问题的代码。
编辑:“几乎”下面的代码正常工作,计时器正在运行但屏幕只会在按下“开始”按钮时更新为新的计时器值。如何自动刷新文本?
public class TestApplet extends JApplet implements ActionListener{
final JTextField _displayField = new JTextField("Countdown", 6);
CountDownTimer clock = new CountDownTimer();
JButton jbtnStart = new JButton("Start");
public void addComponentToPane(Container pane) {
JPanel mainPanel = new JPanel();
mainPanel.add(jbtnStart);
mainPanel.add(_displayField);
pane.add(mainPanel);
jbtnStart.addActionListener(this);
}
public void init() {
TestApplet testApplet = new TestApplet();
testApplet.setVisible(true);
testApplet.addComponentToPane(this.getContentPane());
this.setSize(200, 100);
}
public void actionPerformed(ActionEvent e) {
if ( e.getSource() == jbtnStart ){
clock.start(_displayField);
}
}
}
// ********************************************************************************
//********************************************************************************
//********************************************************************************
class CountDownTimer {
private static final int N = 60;
private final ClockListener cl = new ClockListener();
private final Timer t = new Timer(1000, cl);
static int count =0;
public int getCount(){
System.out.println(count);
return count;
}
public void setCount(int n){
count = n;
}
public CountDownTimer() {
t.setInitialDelay(0);
}
public void start(JTextComponent c) {
t.start();
Boolean bool = false;
while ( bool ==false){
c.setText( "Starting new game in... "+ this.getCount() );
bool = ( this.getCount()<10 );
}
}
private class ClockListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
count %= N;
count++;
setCount(count);
}
}
}
答案 0 :(得分:4)
ActionListener中有一个阻止EDT的while循环。更新显示字段的代码不应该在ActionListener中。
相反,此代码应该在Timer类中。然后,只要Timer触发,您只需减去一个并更新显示字段。当计数达到零时,停止计时器。
此外,您的CountDownTimer不应扩展JFrame。它只是一个类,与框架无关。
编辑:
以下是Swing Timer的一个简单用法:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
public class TimerTime extends JFrame implements ActionListener
{
JLabel timeLabel;
public TimerTime()
{
timeLabel = new JLabel( new Date().toString() );
getContentPane().add(timeLabel, BorderLayout.NORTH);
}
public void actionPerformed(ActionEvent e)
{
timeLabel.setText( new Date().toString() );
}
public static void main(String[] args)
{
TimerTime frame = new TimerTime();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setVisible(true);
int time = 1000;
javax.swing.Timer timer = new javax.swing.Timer(time, frame);
timer.setInitialDelay(1);
timer.start();
}
}
答案 1 :(得分:1)
我们一直在争论是否有可能使用后台线程的解决方案,所以我使用辅助线程编写了一个解决方案,它运行正常。
“N”常数稳定倒计时的长度
公共类TestApplet扩展JApplet实现了ActionListener {
JTextField _displayField;
CountDownTimer clock;
JButton jbtnStart;
Thread thread;
public TestApplet(){
this.jbtnStart = new JButton("Start");
this._displayField = new JTextField("Countdown", 30);
this.clock = new CountDownTimer(_displayField);
this.thread = null;
}
public void addComponentToPane(Container pane) {
JPanel mainPanel = new JPanel();
mainPanel.add(jbtnStart);
mainPanel.add(_displayField);
pane.add(mainPanel);
jbtnStart.addActionListener(this);
}
public void init() {
TestApplet testApplet = new TestApplet();
testApplet.setVisible(true);
testApplet.addComponentToPane(this.getContentPane());
this.setSize(200, 100);
}
public void actionPerformed(ActionEvent e) {
if ( e.getSource() == jbtnStart ){
if(thread != null){
thread.interrupt();
}
thread = new Thread(clock);
thread.start();
}
}
}
/ <强> * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * *** 强> / / <强> 强> 的 ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * * 强> / / <强> * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * **** 强> /
public class CountDownTimer implements Runnable{
private static final int N = 60;
JTextComponent c;
static int count =0;
public int getCount(){
System.out.println(count);
return count;
}
public void setCount(int n){
count = n;
}
public CountDownTimer(JTextComponent c) {
this.c = c;
}
@Override
public void run() {
try {
for(int i=N; i>0; i--){
setCount(i);
c.setText( "Starting new game in... "+ this.getCount() );
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
setCount(0);
}
}
}
答案 2 :(得分:0)
如何使用并发进行倒计时?
public void actionPerformed(ActionEvent e) {
if ( e.getSource() == jbtnStart ){
//You should start your new thread here
Thread thread = Thread(new Runnable(){
public void run(){
clock.start();
Boolean bool = false;
while ( bool ==false){
//You can not modify the UI from a secondary thread, so you should call to some
//method in the GUI thread...
_displayField.setText( "Starting new game in... "+ clock.getCount() );
bool = ( clock.getCount()==5 );
}
}
thread.start();
}
}
}
注意:强> 代码是由心脏完成的,所以容易出现一些错误,但它表达了主要观点。