2012-02-19 91 views
3

不錯的工作,現在我只想知道爲什麼如果我加入while循環指令System.out.println下面的進度顯示在這兩個cmd和Pgbar在桂? :JProgressBar不更新,找不到線索

while(progress < 99){ 
    System.out.println("into while of PBar Thread progress = "+progress); 
    if(progress != Path.operationProgress){ 
    operationProgressBar.setValue(progress); 
    progress = Path.operationProgress; 
    operationProgressBar.repaint(); } } 

需要一些幫助身邊,我不能得到的JProgressBar更新,我 不能使用SwingWorker的,我必須解決這個問題離不開它。變量 Path.operationProgress是一個來自「Path」類的實例的靜態變量,它從另一個線程更新,所以我認爲PBar 和Path實例都在用戶線程中執行,而不是在EDT中執行 EDT。這裏是進度條的代碼:

import javax.swing.*; 
    public class Pbar extends Thread { 
     JProgressBar operationProgressBar; 
     public Pbar(JProgressBar operationProgressBar) { 
      this.operationProgressBar = operationProgressBar; 
     } 

     @Override 
     public void run() { 
      int progress = Path.operationProgress; 
      while(progress < 99) { 
       if(progress != Path.operationProgress) { 
        operationProgressBar.setValue(progress); 
        progress = Path.operationProgress; 
        operationProgressBar.repaint(); 
       }}} 
    } 

這是啓動線程的操作:

private javax.swing.JProgressBar operationProgressBar; 
private javax.swing.JLabel pathImage; 
private javax.swing.JButton simulatedAnnelingButton; 

public class TSPGUI extends javax.swing.JFrame { 

    TSPMG tspInstance; 
    Path p, result; 
    String filename = ""; 
    int neighborHood_Type = 1, i = 0; 
    // ......Constructor Stuff and init() 

private void simulatedAnnelingButtonActionPerformed(java.awt.event.ActionEvent evt) 

{
主題SA =新的Thread(){ @覆蓋 公共無效的run (){ result = p.SimulatedAnnealing(neighborHood_Type); String lastCostString = result.Cost()+「」; lastCostLabel.setText(lastCostString); }}; sa.start(); Pbar pb = new Pbar(operationProgressBar); pb.start(); } // 一些其他的東西...... }

+1

儘管你的關懷嘗試做的事情在後臺線程,你的問題聞起來像一個線程問題 - 要麼或不確定JProgressBar更新是不顯示的一個。沒有更多的代碼,但很難說。如果上面的代碼在後臺線程上運行,則必須小心地調用EDT上的進度條setValue(...),雖然這不能解決問題,但可能會防止出現間歇性異常。我建議你向我們展示更多代碼,最好是[sscce](http://sscce.org)。 – 2012-02-19 13:28:13

+0

請對代碼塊使用一致的邏輯縮進,並且在每一個代碼行之後不需要空行! – 2012-02-19 13:38:44

+0

另外,你應該努力實現Runnable而不是擴展Thread。另外你如何運行線程?你是在調用'start()'還是'run()'? ......你的問題會導致更多的問題再次被[sscce](http://sscce.org)回答。我知道我在這裏聽起來像是一個破碎的記錄,但是如果寫得好的話,那些東西是很有幫助的。 – 2012-02-19 13:43:33

回答

0

我會使用PropertyChangeListener來讓退火進度值成爲類的「綁定」屬性。如果需要的話,任何觀察者都可以關注這個屬性。例如:

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

import javax.swing.*; 
import javax.swing.event.SwingPropertyChangeSupport; 

@SuppressWarnings("serial") 
public class TspGui2 extends JPanel { 
    private static final String ANNEALING_PROGRESS = "Annealing Progress"; 
    private JProgressBar progBar = new JProgressBar(0, 100); 
    private JLabel valueLabel = new JLabel(); 
    private JButton beginAnnealingBtn = new JButton("Begin Annealing"); 
    private MyAnnealing myAnnealing = new MyAnnealing(this); 

    public TspGui2() { 
     beginAnnealingBtn.addActionListener(new ActionListener() { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      beginAnnealing(); 
     } 
     }); 
     myAnnealing.addPropertyChangeListener(new PropertyChangeListener() { 

     @Override 
     public void propertyChange(PropertyChangeEvent evt) { 
      if (evt.getPropertyName().equals(MyAnnealing.ANNEALING)) { 
       // be sure this is done on the EDT 
       SwingUtilities.invokeLater(new Runnable() { 
        public void run() { 
        int annealedValue = myAnnealing.getAnnealedValue(); 
        setValue(annealedValue); 
        if (annealedValue >= MyAnnealing.MAX_ANNEALED_VALUE) { 
         beginAnnealingBtn.setEnabled(true); 
        } 
        } 
       }); 
      } 
     } 
     }); 
     progBar.setString(ANNEALING_PROGRESS); 
     progBar.setStringPainted(true); 

     JPanel northPanel = new JPanel(new GridLayout(1, 0)); 
     northPanel.add(beginAnnealingBtn); 
     northPanel.add(valueLabel); 

     setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); 
     add(northPanel); 
     add(progBar); 
    } 

    public void setValue(int value) { 
     valueLabel.setText("Value:" + value); 
     progBar.setValue(value); 
    } 

    public void beginAnnealing() { 
     beginAnnealingBtn.setEnabled(false); 
     setValue(0); 
     myAnnealing.reset(); 
     new Thread(new Runnable() { 
     public void run() { 
      myAnnealing.beginAnnealing(); 
     } 
     }).start(); 
    } 

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

     JFrame frame = new JFrame("TspGui2"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_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 MyAnnealing { 
    public static final String ANNEALING = "Annealing"; 
    public static final int MAX_ANNEALED_VALUE = 100; 
    private SwingPropertyChangeSupport propChangeSupport = 
     new SwingPropertyChangeSupport(this); 
    private TspGui2 gui; 
    private int annealedValue; 

    public MyAnnealing(TspGui2 gui) { 
     this.gui = gui; 
    } 

    public void addPropertyChangeListener(
     PropertyChangeListener listener) { 
     propChangeSupport.addPropertyChangeListener(listener); 
    } 

    public void removePropertyChangeListener(
     PropertyChangeListener listener) { 
     propChangeSupport.removePropertyChangeListener(listener); 
    } 

    public void reset() { 
     setAnnealedValue(0); 
    } 

    // simulate some long process... 
    public void beginAnnealing() { 
     long sleepDelay = 100; 
     while (annealedValue < MAX_ANNEALED_VALUE) { 
     setAnnealedValue(annealedValue + 1); 
     try { 
      Thread.sleep(sleepDelay); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     } 
    } 

    public int getAnnealedValue() { 
     return annealedValue; 
    } 

    private void setAnnealedValue(int value) { 
     final int oldValue = this.annealedValue; 
     this.annealedValue = value; 
     propChangeSupport.firePropertyChange(ANNEALING, oldValue, annealedValue); 
    } 
} 
+0

@TheEighthEro:你不能在評論中發佈代碼,因爲它是完全不可讀的。 – 2012-02-19 18:29:46

+0

原始文章已更新。 – 2012-02-19 18:38:01

+0

@TheEighthEro:考慮格式化新代碼並澄清問題。另外,如果你大大簡化你的代碼,並且實際上創建併發布了一個類似於我上面發佈的[sscce](http://sscce.org)的幫助來解決你的問題會容易得多。長時間運行的退火過程可以用一個簡單的'Thread.sleep(...)'來模擬。 – 2012-02-19 18:47:02

5

如果您不能使用SwingWorker然後用SwingUtilities.invokeLater,如:

if (progress != Path.operationProgress) { 
    final int progressCopy = progress; // Probably not final so copy is needed 
    SwingUtilities.invokeLater(new Runnable() { 
     @Override 
     void run() { 
      operationsProgressBar.setValue(progressCopy); 
     } 
    }); 
} 

注:執行此操作時,在run使用任何事物都有是最終的,或者必須有其他措施來訪問這些變量。這個代碼在這方面是象徵性的。

您需要對事件派發線程外的Swing組件執行操作,但沒有辦法解決此問題。

+0

+不錯的答案+1 – mKorbel 2012-02-19 15:01:29

+0

不錯,但正如@Hovercraft FullOfEels所說,這似乎並不能解決問題。 – 2012-02-19 17:04:45

+0

@TheEighthEro:你仍然有碰撞的線程,甚至可能不是EDT,但很可能是一個後臺線程相撞。我強烈地敦促你發佈很小的代碼,那就是* compilable *和* runnable *,對於我們來說,[sscce](http://sscce.org)。我還建議您不要對變量進行100%輪詢,而應該讓觀察者在結果發生變化時將結果推送給觀察者。 – 2012-02-19 17:28:43