2012-02-19 89 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