我只是希望这个程序等待计时器。我想要的只是让程序暂停两秒钟。我希望这个程序能够显示"开始,"等待两秒钟,直到计时器结束,然后显示"开始,完成等待,完成。"如何让这个程序等待计时器完成?我相信它目前在一个单独的线程中创建计时器,而不是暂停主线程,因此它显示," 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();
}
}
答案 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 Swing和How 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();
}
}