2

我正在尝试在 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);
        }
    }
}
4

3 回答 3

4

在阻塞 EDT 的 ActionListener 中有一个 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();
    }
}
于 2013-02-12T16:19:14.983 回答
1

我们一直在争论是否可以使用带有后台线程的解决方案,所以我使用辅助线程编写了一个解决方案并且它工作正常。

  • “getCount”和“setCount”方法可有可无
  • “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);
        }
    }
}
于 2013-02-13T01:29:46.460 回答
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();

            }


     }
}  

注意: 代码是用心编写的,因此容易出现一些错误,但它表达了要点。

于 2013-02-12T16:17:55.200 回答