2015-09-25 43 views
1

做我有这样的代码:GUI卡住如果循环内EDT

Thread T=new Thread(new Runnable(){ 
    public void run(){ 
     SwingUtilities.invokeLater(new Runnable(){ 
      public void run(){ 
       for (int i=0;i<18;i++){ 
        int percent=(int)(((i+1)*100)/18); 
        try { 
         lblNewLabel.setText("Loading... ("+percent+"%)"); 
         Thread.sleep(1000); 
        } 
        catch (Exception e) { 
         e.printStackTrace(); 
        } 
       } 
      } 
     }); 
    } 
}); 

我的问题是,我的标签不会改变它的文本此线程盯着之后,反而会留在旧文本(在此代码标签上加上“加载...(0%)”文本)。 有没有办法避免这么做?

然后......如果我叫了invokeLater只在我的setText调用是这样的:

SwingUtilities.invokeLater(new Runnable(){ 

     public void run(){ 

      lblNewLabel.setText("Loading...("+percent+"%)"); 
     } 
    }); 

它会被称为18倍。这是一个好方法吗?或者最好不要调用invokeLater方法那么多次?

谢谢

+0

好像你已经使用了'为“事件分派线程” edt'标签,但实际上不是什么它是。看看[这里](http://stackoverflow.com/tags/edt/info)。我编辑删除它从这个问题(将在审查后可见)。 – Lii

+0

特赦,不知道。 –

回答

1

以下工作:

public class UIThreadTest { 

    private JFrame mainFrame; 
    private JLabel labelStatus; 
    private JButton buttonProcess; 

    public static void main(String[] args) { 
     final UIThreadTest ui = new UIThreadTest(); 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       ui.initGUI(); 
      } 
     }); 
    } 

    public void initGUI() { 
     mainFrame = new JFrame("View"); 
     mainFrame.getContentPane().setLayout(new BorderLayout()); 
     mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     mainFrame.setSize(200, 200); 
     mainFrame.setVisible(true); 
     mainFrame.setLocationRelativeTo(null); 

     labelStatus = new JLabel("Status..."); 
     mainFrame.getContentPane().add(labelStatus, BorderLayout.NORTH); 

     buttonProcess = new JButton("Start"); 
     buttonProcess.addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       Runnable startLoop = new StartLoop(); 
       Thread startLoopThread = new Thread(startLoop); 
       startLoopThread.start(); 
      } 

     }); 
     mainFrame.getContentPane().add(buttonProcess, BorderLayout.SOUTH); 
    } 

    private void updateStatus(final int val) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       labelStatus.setText("Loading... (" + val + "%)"); 
      } 
     }); 

    } 

    private void runForLoop() { 
     for (int i = 0; i < 18; i++) { 
      int percent = (int) (((i + 1) * 100)/18); 
      updateStatus(percent); 
      try { 
       Thread.sleep(1000L); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

    private class StartLoop implements Runnable { 
     @Override 
     public void run() { 
      runForLoop(); 
     } 

    } 
} 
+0

真的非常感谢您的帮助,我也接近这个解决方案..但是..调用这么多次invokeLater是个好主意吗?这会效率低下吗?或者这样做是个好主意?在这段代码中,它被称为18次...... –

+0

我认为它会和其他方法调用18次一样好。 invokeLater文档说:“导致doRun.run()在AWT事件派发线程上异步执行,这将在处理完所有未处理的AWT事件后发生。”你为什么认为这可能是低效率的?“我们也没有阻止美国东部时间。你可能也喜欢[link](http://stackoverflow.com/questions/9289331/edt-and-other-thread-relations-regard-重绘-方法-java的) –