2014-09-21 194 views
3

我有一個使用JProgressBar的GUI。 GUI具有JBUTTONs是調用下面的代碼:我什麼時候應該使用javax.swing.SwingUtilities.invokeLater()?

public void updateProgressBar(int x) { 
    System.out.println(javax.swing.SwingUtilities.isEventDispatchThread()); 
    healthBar.setValue(x); 
} 

,但我也做了一個循環,定期調用相同的方法。

public class Loop implements Runnable { 
    public void run() { 
     while (true) { Thread.sleep(2000); updateProgressBar(0); } 
    } 
} 

現在,據我所知,任何改變我的GUI需要從EDT執行。 JProgressBar.setValue(x)更改了我的GUI,並且當它從Loop類中調用時,isEventDispatchThread檢查失敗,這是非常好的和可理解的。然而,我不明白的是,如果這也意味着我應該使用setValue()上的SwingUtilities.invokeLater()。我擔心的是,因爲我不知道setValue()實際上是如何工作的,所以我不必要地使用invokeLater(),甚至在使用它時甚至破壞了某些東西。

我不知道如何問我的問題:如果我知道改變我的GUI的方法不是從EDT調用的,那麼我是否也知道我必須使用invokeLater()

+0

那'Loop'類是不好的,您同時使用無限'while'以及'Thread.sleep()方法' – BitNinja 2014-09-21 00:20:17

+0

你告訴我,這是不好的,因爲我用的主題.sleep()在無限循環中,還是因爲我不應該在任何上下文中使用無限循環和Thread.sleep()? – user2651804 2014-09-21 00:24:40

+0

創建一個線程安全的TimerTask ... – 2014-09-21 00:24:49

回答

5

一個可能的解決方案是創建一個檢查,如果線程是EDT,如果是直接更新吧,否則它排在美國東部時間的方法:

public void updateProgressBar(int value) { 
    progressBar.setValue(value); 
} 

public void safeUpdateProgressBar(final int value) { 
    if (SwingUtilities.isEventDispatchThread()) { 
     updateProgressBar(value); 
    } else { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      updateProgressBar(value); 
     } 
     }); 
    } 
} 

但也有許多方法可以皮膚這隻貓。例如,

import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.KeyEvent; 
import java.beans.PropertyChangeEvent; 
import java.beans.PropertyChangeListener; 

import javax.swing.*; 

public class ProgExample extends JPanel { 
    private JProgressBar progressBar = new JProgressBar(0, 100); 

    public ProgExample() { 
     progressBar.setBorderPainted(true); 
     progressBar.setStringPainted(true); 
     add(progressBar); 
     add(new JButton(new ProgressAction1("Action 1", KeyEvent.VK_1, this))); 
     add(new JButton(new ProgressAction2("Action 2", KeyEvent.VK_2, this))); 
     add(new JButton(new ProgressAction3("Action 3", KeyEvent.VK_3, this))); 
    } 

    public void updateProgressBar(int value) { 
     progressBar.setValue(value); 
    } 

    public void safeUpdateProgressBar(final int value) { 
     if (SwingUtilities.isEventDispatchThread()) { 
     updateProgressBar(value); 
     } else { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       updateProgressBar(value); 
      } 
     }); 
     } 
    } 

    private static void createAndShowGui() { 
     ProgExample mainPanel = new ProgExample(); 

     JFrame frame = new JFrame("ProgExample"); 
     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 
} 

class ProgressAction1 extends AbstractAction { 
    private static final int MAX_VALUE = 100; 
    protected static final long SLEEP_TIME = 100; 
    protected static final int STEP = 2; 
    private ProgExample gui; 

    public ProgressAction1(String name, int mnemonic, ProgExample gui) { 
     super(name); 
     putValue(MNEMONIC_KEY, mnemonic); 
     this.gui = gui; 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     new Thread(new Runnable() { 
     private int value = 0; 
     @Override 
     public void run() { 
      while (value <= MAX_VALUE) { 
       gui.safeUpdateProgressBar(value); 
       value += STEP; 
       try { 
        Thread.sleep(SLEEP_TIME); 
       } catch (InterruptedException e) {} 
      } 
      gui.safeUpdateProgressBar(MAX_VALUE); 
     } 
     }).start(); 
    } 
} 

class ProgressAction2 extends AbstractAction { 
    private static final int MAX_VALUE = 100; 
    protected static final long SLEEP_TIME = 100; 
    protected static final int STEP = 2; 
    private ProgExample gui; 

    public ProgressAction2(String name, int mnemonic, ProgExample gui) { 
     super(name); 
     putValue(MNEMONIC_KEY, mnemonic); 
     this.gui = gui; 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     final SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { 
     private int value = 0; 

     @Override 
     protected Void doInBackground() throws Exception { 
      while (value <= MAX_VALUE) { 
       setProgress(value); 
       value += STEP; 
       try { 
        Thread.sleep(SLEEP_TIME); 
       } catch (InterruptedException e) {} 
      } 
      setProgress(MAX_VALUE); 
      return null; 
     } 
     }; 
     worker.addPropertyChangeListener(new PropertyChangeListener() { 

     @Override 
     public void propertyChange(PropertyChangeEvent pcEvt) { 
      if ("progress".equals(pcEvt.getPropertyName())) { 
       gui.updateProgressBar(worker.getProgress()); 
      } 
     } 
     }); 
     worker.execute(); 
    } 
} 

class ProgressAction3 extends AbstractAction { 
    private static final int MAX_VALUE = 100; 
    protected static final int SLEEP_TIME = 100; 
    protected static final int STEP = 2; 
    private ProgExample gui; 

    public ProgressAction3(String name, int mnemonic, ProgExample gui) { 
     super(name); 
     putValue(MNEMONIC_KEY, mnemonic); 
     this.gui = gui; 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     new Timer(SLEEP_TIME, new ActionListener() { 
     int value = 0; 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      if (value <= MAX_VALUE) { 
       gui.updateProgressBar(value); 
       value += STEP; 
      } else { 
       gui.updateProgressBar(MAX_VALUE); 
       ((Timer) e.getSource()).stop(); 
      } 

     } 
     }).start(); 
    } 
} 
相關問題