2017-02-15 43 views
2

我的JPanel出了問題。我用接口構建了一個html/css scraper。該接口具有一個JTextArea,可以使用「找到HTML」和「保存的文件成功」完成刮板完成的步驟進行更新。我想在代碼運行時將這些消息添加到JTextArea中。一個簡單的檢查顯示更新與observerpattern一起工作,但所有消息在所有代碼完成前都不顯示。Java Jpanel只在完成代碼後更新

示例代碼從observerable類(觸發像100次):

private void addItem(String line, char type, String classOrId) { 
    String[] lineSplit = line.split(classOrId+"="+type); 
    lineSplit = lineSplit[1].split(""+type); 
    lineSplit = lineSplit[0].split(" "); 
    for (String a : lineSplit) { 
     if(classOrId == "id"){ 
      if (!usedIds.contains(a)) { 
       usedIds.add(a); 
      } 
     } 
     else if(classOrId == "class"){ 
      if (!usedClasses.contains(a)) { 
       usedClasses.add(a); 
      } 
     } 
     consoleText = consoleText + "Class \"" + a + "\" is found."; 
     setChanged(); 
     notifyObservers(); 
    } 
} 

示例代碼從觀察者類:

public class ScraperView extends JPanel implements Observer { 
    Scraper scraper; 
    public ScraperView(Scraper scraper){ 
     this.scraper = scraper; 
     scraper.addObserver(this); 
     this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 
     refresh(); 
    } 

    private void refresh() { 
     System.out.println("TrIGGER"); 
     removeAll(); 
     int removedClasses = scraper.getRemovedClasses(); 
     int totalClasses = scraper.getTotalClasses(); 
     JLabel classesText = new JLabel(" Total Classes:  "+ Integer.toString(totalClasses)); 
     JLabel removedClassesText = new JLabel(" Removed Classes: "+ Integer.toString(removedClasses)); 
     this.add(classesText); 
     this.add(removedClassesText); 
     this.revalidate(); 
     this.repaint(); 
    } 
    @Override 
    public void update(Observable o, Object arg) { 
     refresh(); 
    } 
} 

有沒有辦法等到JPanel的更新?我注意到每次都會觸發代碼,但不更新。

+0

我建議你切換到JavaFX,Swing應該被棄用。如果您必須使用Swing,請將邏輯移至另一個可定期更新UI的線程。 – MustSeeMelons

+0

你的代碼在'Event Dispatch Thread(EDT)'上執行,並且在所有代碼完成執行之前,Swing不能重新繪製自己。您的代碼需要在單獨的線程中運行。閱讀[併發在Swing]上的Swing教程部分(http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html)。瞭解更多信息 – camickr

回答

1

您應該看看SwingWorker類,它旨在在線程中執行任務,同時更新UI。

0

你正在創建並添加新的JLabel s每當你更新這是一個壞主意,你應該創建一次標籤然後更新它們,你還應該確保你更新它們在你的UI線程上可以用SwingUtilities.invokeLater(Runnable)

public class ScraperView extends JPanel implements Observer { 
    Scraper scraper; 
    JLabel classesText = new JLabel(); 
    JLabel removedClassesText = new JLabel(); 

    public ScraperView(Scraper scraper){ 
     this.scraper = scraper; 
     scraper.addObserver(this); 
     this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 
     this.add(classesText); 
     this.add(removedClassesText); 
     refresh(); 
    } 

    private void refresh() { 
     System.out.println("TrIGGER"); 
     int removedClasses = scraper.getRemovedClasses(); 
     int totalClasses = scraper.getTotalClasses(); 
     classesText.setText(" Total Classes:  "+ Integer.toString(totalClasses)); 
     removedClassesText.setText(" Removed Classes: "+ Integer.toString(removedClasses)); 
    } 
    @Override 
    public void update(Observable o, Object arg) { 
     SwingUtilities.invokeLater(this::refresh); 
    } 
}