在倒数计时器上使用windowFocusListener

时间:2016-06-12 14:05:03

标签: java swing window focus

我正在尝试制作一个只在窗口位于屏幕顶部时才会运行的倒数计时器。

我试过这个:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class TimerVisible extends JFrame implements WindowFocusListener{
    static TimerVisible frame = new TimerVisible("chrono",2,1,3);//I set a random time
    JTextArea display;
    private Counter counter;

    public static void main(String[] args) {
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.addComponentsToPane();
        frame.pack();
        frame.setVisible(true);
    }

    private void addComponentsToPane() {
        display = new JTextArea();
        display.setEditable(true);
        JScrollPane scrollPane = new JScrollPane(display);
        scrollPane.setPreferredSize(new Dimension(500, 450));
        getContentPane().add(scrollPane, BorderLayout.CENTER);
        addWindowFocusListener(this);
    }

    public TimerVisible(String name, int hours, int minutes, int secondes) {
        super(name);
        counter=new Counter(hours, minutes, secondes); //Counter is in secondes but is created with hours, minutes and seconds
    }


    public void windowGainedFocus(WindowEvent e) {
        displayMessage("WindowFocusListener method called: windowGainFocus.");
        try{
            while(counter.getCounter()!=0){
                Thread.sleep(1000);
                displayMessage(counter.toString());
                counter.decrement();
            }
        }
        catch(InterruptedException exc){
            System.exit(-1);
        }
    }

    public void windowLostFocus(WindowEvent e) {
        displayMessage("WindowFocusListener method called: windowLostFocus.");
    }

    private void displayMessage(String msg) {
        display.append(msg+"\n");
        System.out.println(msg);
    }
}

当我运行这个程序时,它会在我的终端而不是窗口上显示消息和倒计时,但如果我在评论下设置while loop,它会正确显示窗口上的消息。有人知道我为什么会有这种差异吗?

谢谢

1 个答案:

答案 0 :(得分:2)

您的while循环正在Swing事件线程上运行,阻止它并阻止它绘制到GUI或与用户交互。请改用Swing Timer。请注意,使用Swing Timer,您将没有while循环,而是重复调用actionPerformed,直到您停止Timer。

这样的事情可能接近工作(代码未经测试)

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.Timer;

public class TimerVisible extends JFrame implements WindowFocusListener{
    private static final int TIMER_DELAY = 1000;
    static TimerVisible frame = new TimerVisible("chrono",2,1,3);//I set a random time
    JTextArea display;
    private Counter counter;
    Timer timer = null;

    public static void main(String[] args) {
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.addComponentsToPane();
        frame.pack();
        frame.setVisible(true);
    }

    private void addComponentsToPane() {
        display = new JTextArea();
        display.setEditable(true);
        JScrollPane scrollPane = new JScrollPane(display);
        scrollPane.setPreferredSize(new Dimension(500, 450));
        getContentPane().add(scrollPane, BorderLayout.CENTER);
        addWindowFocusListener(this);
    }

    public TimerVisible(String name, int hours, int minutes, int secondes) {
        super(name);
        counter=new Counter(hours, minutes, secondes); //Counter is in secondes but is created with hours, minutes and seconds
    }


    public void windowGainedFocus(WindowEvent e) {
        displayMessage("WindowFocusListener method called: windowGainFocus.");
        if (timer != null && timer.isRunning()) {
            return;
        }

        timer = new Timer(TIMER_DELAY, new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                if (counter.getCounter() <= 0) {
                    timer.stop();
                } else {
                    displayMessage(counter.toString());
                    counter.decrement();
                }

            }
        });
        timer.start();
    }

    public void windowLostFocus(WindowEvent e) {
        displayMessage("WindowFocusListener method called: windowLostFocus.");
    }

    private void displayMessage(String msg) {
        display.append(msg+"\n");
        System.out.println(msg);
    }
}