2013-09-16 3 views
0

Я сделал очень простой код, чтобы показать его здесь, у меня есть кнопка, которая должна показать JDialog, чтобы проверить статус выполнения, я использую вызов поздно, чтобы пройти через EDT, и мой цикл не находится в метод run, так почему же не обновляется моя панель? здесь кодJProgressBar не обновляется

import javax.swing.JButton; 
import javax.swing.JDialog; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JProgressBar; 
import javax.swing.JTextField; 
import javax.swing.SwingUtilities; 

import java.awt.BorderLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

public class JBarEx extends JFrame { 
private JTextField progStatus = new JTextField("Undefined"); 
private JButton dialogBtn = new JButton("Show Progression dialog"); 
final JDialog dlg = new JDialog((JFrame) null, "prog Title", false); 
final JProgressBar dpb = new JProgressBar(0, 100); 

public JBarEx() { 
    JPanel pan = new JPanel(); 
    dialogBtn.addActionListener(new ActionListener() { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      // TODO Auto-generated method stub 
      showProgress(); 
     } 
    }); 
    progStatus.setEditable(false); 
    pan.add(progStatus); 
    pan.add(dialogBtn); 
    setContentPane(pan); 
    this.setSize(200, 100); 
    setVisible(true); 
} 

public void showProgress() { 
    dlg.add(BorderLayout.CENTER, dpb); 
    dlg.add(BorderLayout.NORTH, new JLabel("prog message")); 
    dlg.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); 
    dlg.setSize(300, 75); 
    dlg.setLocationRelativeTo(null); 
    dlg.setVisible(true); 

    for (int i = 0; i < 100; i++) { 
     final int ii = i; 
     try { 
      Thread.sleep(25); 
      SwingUtilities.invokeLater(new Runnable() { 

       @Override 
       public void run() { 
        updateBar(ii); 

       } 
      }); 
     } 
     catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 

} 

public void updateBar(int newValue) { 
    dpb.setValue(newValue); 
} 

public static void main(String[] args) { 
    JBarEx jbx = new JBarEx(); 
} 

}

+0

Вы блокирующих AEDT, предотвращая его формы обработки любой дополнительный запрос краски.До тех пор, пока петля не соревнуется. Решение bett должно было бы использовать SwingWorker для запуска вашей задачи/цикла в фоновом режиме и обновления для обновления прогресса, которые могут быть обработаны в EDT. См. [* This *] (http://stackoverflow.com/questions/15199091/progress-bar-java/15199220#15199220) для примера – MadProgrammer

ответ

7

showProgress Вашего метода в настоящее время выполняется в контексте событий диспетчерской темы. EDT отвечает за, среди прочего, обработку запросов краски. Это означает, что до тех пор, пока выполняется ваш for-loop, EDT не может обрабатывать любые новые запросы на рисование (или обрабатывать события invokeLater), поскольку он блокирует EDT.

Несмотря на то, что существует множество возможных путей решения проблемы, на основе вашего примера кода проще всего использовать SwingWorker.

У этого есть возможность разрешить выполнение долгосрочной задачи фоновой нитью (освобождение EDT), но также позволяет вам обновлять publishing (при необходимости), чтобы они могли обрабатываться в EDT и также предоставляет удобное уведомление progress.

Например ...

enter image description here

import java.awt.BorderLayout; 
import java.awt.EventQueue; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.Insets; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.beans.PropertyChangeEvent; 
import java.beans.PropertyChangeListener; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JProgressBar; 
import javax.swing.SwingWorker; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.border.EmptyBorder; 

public class SwingWorkerProgress { 

    public static void main(String[] args) { 
     new SwingWorkerProgress(); 
    } 

    public SwingWorkerProgress() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     private JProgressBar pbProgress; 
     private JButton start; 

     public TestPane() { 

      setBorder(new EmptyBorder(10, 10, 10, 10)); 
      pbProgress = new JProgressBar(); 
      setLayout(new GridBagLayout()); 
      GridBagConstraints gbc = new GridBagConstraints(); 
      gbc.insets = new Insets(4, 4, 4, 4); 
      gbc.gridx = 0; 
      gbc.gridy = 0; 
      add(pbProgress, gbc); 

      start = new JButton("Start"); 
      gbc.gridy++; 
      add(start, gbc); 

      start.addActionListener(new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        start.setEnabled(false); 
        ProgressWorker pw = new ProgressWorker(); 
        pw.addPropertyChangeListener(new PropertyChangeListener() { 

         @Override 
         public void propertyChange(PropertyChangeEvent evt) { 
          String name = evt.getPropertyName(); 
          if (name.equals("progress")) { 
           int progress = (int) evt.getNewValue(); 
           pbProgress.setValue(progress); 
           repaint(); 
          } else if (name.equals("state")) { 
           SwingWorker.StateValue state = (SwingWorker.StateValue) evt.getNewValue(); 
           switch (state) { 
            case DONE: 
             start.setEnabled(true); 
             break; 
           } 
          } 
         } 

        }); 
        pw.execute(); 
       } 
      }); 

     } 
    } 

    public class ProgressWorker extends SwingWorker<Object, Object> { 

     @Override 
     protected Object doInBackground() throws Exception { 

      for (int i = 0; i < 100; i++) {   
       setProgress(i); 
       try { 
        Thread.sleep(25); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 

      return null; 
     } 
    } 
} 

Заканчивать Concurrency in Swing для более подробной информации

0
for (int i = 0; i < 0; i++) { 

Вы никогда не будете ввести этот код, поэтому никогда не будет вызывать updateBar метод (..)

я должен быть больше 0 в этом случае. Если 1, то updateBar будет вызываться один раз, если 2, то updateBar будет называться дважды и т.д.

также довольно чем делать

Thread.sleep(25); 

посмотрит на Java executors, как это поможет с планированием и удалить необходимость сна

1

Даже если вы исправите цикл, как указали другие, вы все равно заблокируете поток отправки событий. Цикл for запускается в showProgress(), который вызывается из прослушивателя событий. Обновления переносятся в очередь событий, но это не обрабатывается до тех пор, пока цикл не завершится.

Вместо этого используйте Swing Timer. Что-то вроде этого:

Timer timer = new Timer(25, new ActionListener() { 
    private int position; 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     position++; 
     if (position < lastPosition) { 
      updateBar(position); 
     } else { 
      ((Timer) e.getSource).stop(); 
     } 
    } 
}); 
timer.start(); 

где lastPosition будет состояние, в котором вы хотите прогресс бар, чтобы остановить.

Не связанный с этой ошибкой, но ошибка по-прежнему не должна создавать компоненты качаний вне потока отправки событий. Лучше всего сделать это с самого начала:

public static void main(String[] args) { 
    SwingUtilities.invokeLater(new Runnable() { 
     @Override 
     public void run() { 
      JBarEx jbx = new JBarEx(); 
     } 
    }); 
} 
+0

+1 для блокировки EDT, -1 для javax.swing.Timer, it не решит проблему, так как это вызовет только обратный вызов через равные промежутки времени. Есть лучшие решения ... – MadProgrammer

+0

@MadProgrammer работает с регулярными интервалами, что делает код вопроса. В зависимости от того, что делает приложение * actual *, 'SwingWorker' может, конечно, быть лучшим решением. – kiheru

+0

SwingWorker спроектирован специально для этой цели. Он может запускать задачу в фоновом режиме и предоставляет два способа для отчета EDT, 'publish' и' setProgress'. Нет необходимости путать с обновлениями, они автоматически отправляются. – MadProgrammer

Смежные вопросы