Java使GUI等待计时器

我只是希望这个程序等待计时器。 我只想让程序暂停两秒钟。 我希望这个程序做的是显示“开始”,等待两秒钟直到计时器结束,然后显示“开始,完成等待,完成”。 如何让这个程序等待计时器完成? 我相信它当前在一个单独的线程中创建了计时器,而不是暂停主线程,所以它显示“Start,Finished”然后等待两秒钟,然后显示“Start,Finished,Finished Waiting”。 这不是我希望事情发生的顺序,我在运行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(); } } 

在调用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秒后Finished Waiting, Finished将附加到JTextArea

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

有关更多详细信息,请参阅Swing中的并发和如何使用Swing Timers

更新…

Swing(和大多数UI)是事件驱动的,也就是说,某些事情会发生并且您会对其做出响应。 例如,使用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 worker = new SwingWorker() { @Override protected String doInBackground() throws Exception { Thread.sleep(2000); publish("Finished waiting, "); return null; } @Override protected void process(List chunks) { for (String text : chunks) { ta.append(text); } } @Override protected void done() { ta.append("Finished"); btn.setEnabled(true); } }; worker.execute(); } }); } } } 

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

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

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