点击按钮,我正在执行一项长任务。我想显示任务已启动的消息。使用swingworker,JOptionPane创建消息框,但其内容保持空白,直到任务完成。我想我的EDT被阻止,因此除非任务完成,否则GUI不会更新。有没有办法显示这个(swingutils.invokelater不能用,因为我需要在任务开始时显示) 示例代码: -
public class myClass {
private JFrame frame;
private display1 dis;
class display1 extends SwingWorker<Void,Void>
{
public Void doInBackground() throws InterruptedException
{
JOptionPane.showMessageDialog(null,
"Task Started");
return null;
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
myClass window = new myClass();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public myClass() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
JButton btnNewButton = new JButton("New button");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
dis=new display1();
dis.execute();
System.out.println("starting");
for(int i=0;i<10000;i++)
System.out.println("this is " +i);// Long task
System.out.println("Finished");
}
});
btnNewButton.setBounds(166, 228, 89, 23);
frame.getContentPane().add(btnNewButton);
}
}
答案 0 :(得分:2)
因为SwingWorker
通知事件调度线程上的任何PropertyChangeListener
,所以只需侦听绑定属性state
。可能的values包括DONE
,PENDING
和STARTED
。此TaskListener
是写入控制台的示例,但在propertyChange()
的实现中更新标签是完全安全的。模态对话是允许的,但是多余的。
答案 1 :(得分:0)
在invokeLater(Runnable);
中运行的任何内容都会发送到Event Dispatch Thread“gui-thread”。您的方法initialize()
在EDT中运行即可,但您需要记住,在EDT中正在处理与UI相关的任何操作。因此,如果用户单击按钮,则在EDT中执行ActionListener
代码。在EDT中执行的任何长时间运行的任务都会阻止处理另一个UI事件。因此,您需要将“长任务”移动到单独的线程e。 G。到SwingWorker
。
如果你需要在运行任务之前显示一些东西,只需在调用swingWorker.execute();
之前放置它(确保给定代码在EDT中执行):
button.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent arg0) {
// we are are in EDT = dialog will be displayed without any problems
JOptionPane.showMessageDialog(null, "About to start");
// executes SwingWorker's doInBackground task
new BackgroundTask().execute();
}
});
以下代码说明了如何使用SwingWorker
:
class BackgroundTask extends SwingWorker<
String/*background task's result type*/,
Integer/*inter-step's result type*/
>
{
/**
* This method is designed to perform long running task in background
* i. e. in "non-EDT" thread = in SwingWorker thread.
*
* After method is completed, {@link #done()} is called, which is
* executed in "EDT" (gui-thread).
*
* Note, you can {@link #publish(Integer)} progress to {@link #process(List<V> chunks)}
* which is executed in "EDT" (gui-thread).
*
* You can also use {@link SwingUtilities#invokeLater(Runnable)}
* to send "message" to "EDT" which contains code to be executed
* This is similar to {@link #publish(Object)} except not-processed-yet
* messages are not collected and processed all at once like in
* {@link #publish(Object)} case.
*/
@Override
protected String doInBackground() throws Exception {
// or you can put JOptionPane.showMessageDialog(null, "About to start");
// in ActionListener before calling swingWorker.execute();
SwingUtilities.invokeLater(() -> JOptionPane.showMessageDialog(null, "About to start"));
// System.out.println("starting");
for(int i = 0; i < 10000; i++) {
// System.out.println(i);
publish(i);
}
// result of the background task
return "Task completed";
}
/**
* Method is executed in "EDT" after calling {@link #publish(Integer)}.
*
* This is the right place to update GUI about inter-step result.
*
* Note, this method is not executed immediately after calling {@link #publish(Integer)},
* since EDT can process at this time sime other GUI tasks.
* Therefore, list contains all inter-step results send from SwingWorker
* to EDT which were not processed yet.
*/
@Override
protected void process(List<Integer> chunks) {
for (int number : chunks) {
textArea.append(number + "\n");
}
}
/**
* Method is executed in "EDT" after {@link #doInBackground()} is finished.
* This is the right place to update GUI about final result.
*/
@Override
protected void done() {
String result = get(); // returns result of the doInBackground();
JOptionPane.showMessageDialog(null, result);
}
}