2012-02-19 2 views
3

хорошая работа, теперь я просто хочу знать, почему, если я добавляю в цикл while, то команда System.out.println ниже прогресса отображается на обоих, cmd и Pgbar в Gui ?? :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 - это статическая переменная из класса «Путь» , и она обновляется из другого потока, поэтому я думаю, что PBar и экземпляры Path выполняются в пользовательских потоках, а не в 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) 

{
са Thread = новая тема() { @Override общественной недействительным бежать() { результат = p.SimulatedAnnealing (соседHood_Type); Строка lastCostString = result.Cost() + ""; lastCostLabel.setText (lastCostString); }}; sa.start(); Pbar pb = новый Pbar (operationProgressBar); pb.start(); } // Некоторые другие вещи ... }

+1

Несмотря на вашу заботу, чтобы попытаться сделать что-то в фоновом потоке, ваша проблема пахнет как вопрос многопоточности - либо, что либо JProgressBar обновляется не один отображается. Однако, без лишнего кода, это трудно сказать. Если приведенный выше код запускается в фоновом потоке, вы должны позаботиться о вызове индикатора выполнения setValue (...) на EDT, хотя это не решит вашу проблему, это может помешать некоторым прерывистым исключениям. Я предлагаю вам показать нам больше кода, желательно [sscce] (http://sscce.org). –

+0

Пожалуйста, используйте последовательный и логический отступ для кодовых блоков, и нет необходимости в пустой строке после каждой строки кода! –

+0

Кроме того, вы должны стремиться реализовать Runnable, а не расширять Thread. Также как вы используете поток? Вы называете 'start()' или 'run()' на нем? ... ваш вопрос приводит к еще большему числу вопросов, на которые лучше всего будет отвечать [sscce] (http://sscce.org). Я знаю, что здесь звучит как сломанная запись, но все дело в том, что эти чертовы вещи настолько полезны, если они хорошо написаны. –

ответ

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: ya не может отправлять комментарии в комментариях, так как это просто нечитаемо. –

+0

оригинальный пост обновлен. –

+0

@ TheEighthEro: рассмотрите форматирование нового кода и уточнение вопроса. Кроме того, было бы намного проще решить вашу проблему, если бы вы упростили свой код и фактически создали и опубликовали [sscce] (http://sscce.org), аналогично тому, что я написал выше. Долгосрочный процесс отжига можно моделировать с помощью простого 'Thread.sleep (...)'. –

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

+0

Ницца, но, как сказал @HovercraftFullOfEels, это, похоже, не решает проблему. –

+0

@ TheEighthEro: У вас все еще есть сталкивающиеся потоки, и это может быть даже не EDT, а скорее вполне фоновый поток, который сталкивается. Я настоятельно призываю вас опубликовать небольшой код, который компилируется * и * runnable * для нас, [sscce] (http://sscce.org). Я также рекомендую, чтобы вы не выполняли 100% опроса своей переменной, а позволяли наблюдаемому выталкивать результат наблюдателям всякий раз, когда он меняется. –