Java使GUI等待计时器

时间:2015-01-28 08:46:25

标签: java multithreading swing timer wait

我只是希望这个程序等待计时器。我想要的只是让程序暂停两秒钟。我希望这个程序能够显示"开始,"等待两秒钟,直到计时器结束,然后显示"开始,完成等待,完成。"如何让这个程序等待计时器完成?我相信它目前在一个单独的线程中创建计时器,而不是暂停主线程,因此它显示," Start,Finished"然后等待两秒钟,然后显示"开始,完成,完成等待。"这不是我希望事情发生的顺序,我在运行GUI时找到了一个简单的计时器示例并且没有找到。感谢您的帮助,以下是代码:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.Timer;

public class GUI extends JFrame {

    private static final long serialVersionUID = 3560258176733156660L;

    public static void main(String[] args) {
        new GUI().setVisible(true);
    }

    private Timer timer;
    private JTextArea area;
    private String text;

    public GUI() {
        setLayout(null);
        setSize(500, 120);
        setTitle("Timer");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        text = "";
        area = new JTextArea(text);
        area.setBounds(0, 0, 500, 120);
        add(area);
        doThings();

    }
    public void doThings() {
        text += "Start, ";
        area.setText(text);
        // Want program to wait for two seconds
        waitForTwoSeconds();
        text += "Finished ";
        area.setText(text);

    }
    public void waitForTwoSeconds() {

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

            @Override
            public void actionPerformed(ActionEvent e) {
                text += "Finished Waiting, ";
                area.setText(text);
                timer.stop();
            }
        });
        timer.start();
    }

}

2 个答案:

答案 0 :(得分:3)

在您致电waitForTwoSeconds并在actionPerformed方法中放置代码后<...

public void doThings() {
    area.setText("Start, ");
    // Want program to wait for two seconds
    waitForTwoSeconds();

}

public void waitForTwoSeconds() {

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

        @Override
        public void actionPerformed(ActionEvent e) {
            area.append("Finished Waiting, ");
            area.append("Finished ");
            timer.stop();
        }
    });
    timer.setRepeats(false);
    timer.start();
}

这会导致Finished Waiting, Finished在您点击按钮后2秒后追加JTextArea ...

你不想在事件调度线程的上下文中执行任何长时间运行/阻塞操作,这会使它看起来像你的程序挂起,因为它有。

有关详细信息,请参阅Concurrency in SwingHow to use Swing Timers

<强>更新...

Swing(和大多数用户界面)都是事件驱动的,也就是说,某些事情会发生并且你会对它做出回应。例如,使用Timer时,计时器会跳闸并且您对事件做出响应。你无法阻止/等待事件调度线程,它只会导致UI停止响应和绘制,这是框架的工作方式,你可以学会忍受它或继续被它挫败(记住,想要什么,让它发挥作用,是两件不同的事情)

但是,您可以执行一些操作,Timer是一个示例,另一个是SwingWorker

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JTextArea ta;

        public TestPane() {
            setLayout(new BorderLayout());
            ta = new JTextArea(10, 20);
            JButton btn = new JButton("Make it so");
            add(new JScrollPane(ta));
            add(btn, BorderLayout.SOUTH);

            btn.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    btn.setEnabled(false);
                    ta.append("Start, ");
                    SwingWorker<String, String> worker = new SwingWorker<String, String>() {

                        @Override
                        protected String doInBackground() throws Exception {
                            Thread.sleep(2000);
                            publish("Finished waiting, ");
                            return null;
                        }

                        @Override
                        protected void process(List<String> chunks) {
                            for (String text : chunks) {
                                ta.append(text);
                            }
                        }

                        @Override
                        protected void done() {
                            ta.append("Finished");
                            btn.setEnabled(true);
                        }

                    };
                    worker.execute();
                }
            });
        }

    }

}

这基本上做的是,在后台线程中,它等待两秒然后(通过publish / process方法)打印“完成等待”,然后打印{{1}返回,doInBackground被(最终)调用并打印出“完成”。

这一切都已完成,因此UI更新发生在Event Dispatching Thread的上下文中,满足Swing的单线程要求

答案 1 :(得分:0)

Ok, so I guess my question should really look like this then:
How do i make the program wait until the waitForTwoSeconds() method is complete before doing area.append("Finished "); ? This is really what I want to accomplish.

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

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

public class GUI extends JFrame {

    private static final long serialVersionUID = 3560258176733156660L;

    public static void main(String[] args) {
        new GUI().setVisible(true);
    }

    private Timer timer;
    private JTextArea area;

    public GUI() {
        setLayout(null);
        setSize(500, 120);
        setTitle("Timer");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        area = new JTextArea("");
        area.setBounds(0, 0, 500, 120);
        add(area);
        doThings();

    }

    public void doThings() {
        area.setText("Start, ");
        // Want program to wait for two seconds
        waitForTwoSeconds();
        // Don't want to do this until waitForTwoSeconds() has finished...
        area.append("Finished ");

    }

    public void waitForTwoSeconds() {

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

            @Override
            public void actionPerformed(ActionEvent e) {
                area.append("Finished Waiting, ");
                timer.stop();
            }
        });
        timer.setRepeats(false);
        timer.start();
    }

}