2017-04-18 126 views
-2

我正在运行一个长按任务按钮。我想显示任务已经开始的消息。使用swingworker,JOptionPane创建消息框,但其内容保留为空,直到任务完成。我想我的EDT正在被阻塞,因此除非任务完成,否则GUI不会更新。有什么办法来证明这个(swingutils.invokelater,因为我需要在任务开始时显示无法使用) 示例代码: -从SwingWorker显示消息(Joptionpane)thread-doInBackground()

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

什么是'display1'?您在EDT的上下文中运行了一项长期任务,这解释了您的UI为空的原因 – MadProgrammer

+0

display1是实现SwingWorker的类的名称。我知道它不工作的原因。我所要求的所有方法都是显示任务已启动并同时执行任务的对话方式(该任务包含操作某些GUI组件) – sam

+2

考虑提供[可运行示例](https://stackoverflow.com/help/mcve )这表明你的问题。这不是代码转储,而是您正在做的事情的一个例子,它突出了您遇到的问题。这会减少混淆和更好的反应 – MadProgrammer

回答

2

因为SwingWorker通知事件调度线程上的任何PropertyChangeListener,只需听取绑定属性state。可能的values包括DONE,PENDINGSTARTED。此TaskListener是写入控制台的示例,但在您的实现propertyChange()中更新标签是完全安全的。模式对话框是允许的但是多余的。

0

invokeLater(Runnable);中运行的任何东西都发送到Event Dispatch Thread“gui-thread”。您的方法initialize()可以在EDT运行,但是您需要记住在EDT中正在处理与UI相关的任何操作。所以如果用户点击按钮,ActionListener代码在EDT中执行。在处理另一个UI事件时在EDT块中执行的任何长时间运行的任务。因此,您需要将您的“长期任务”移至独立线程e。 G。到SwingWorker

如果您需要在运行任务之前显示的东西,只是把它调用swingWorker.execute();(确保,因为代码是在美国东部时间执行)之前:

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); 
    } 
} 
+0

*“我想显示一条消息,表明任务已经开始”* – MadProgrammer

+0

@MadProgrammer在写入时会忘记,我会更新我的答案。 – matoni

+0

另请注意,无法达到安全点的繁忙循环,例如(http://stackoverflow.com/q/35154352/230513)。 – trashgod