2012-06-26 4 views
1

Я хотел бы сделать JProgressBar в новом JDialog, ведьма будет в отдельном потоке от основной логики. Поэтому я могу начать неопределенный прогресс, просто создав новый JDialog и завершая этот прогресс с удалением JDialog. Но мне сложно это сделать, потому что после появления JDialog он не показывает никаких компонентов (включая JProgressBar) до тех пор, пока не будет выполнена логика основного потока (SwingUtilities).JProgressBar в новой теме JDialog

Thread включая JDialog:

package gui.progress; 

public class ProgressThread extends Thread { 
    private ProgressBar progressBar = null; 

    public ProgressThread() { 
     super(); 
    } 

    @Override 
    public void run() { 
     progressBar = new ProgressBar(null); 
     progressBar.setVisible(true); 
    } 

    public void stopThread() { 
     progressBar.dispose(); 
    } 
} 

JProgressBar метод переключения:

private static ProgressThread progressThread = null; 
... 
public static void toggleProcessBar() { 
    if(progressThread == null) { 
     progressThread = new ProgressThread(); 
     progressThread.start(); 
    } else { 
     progressThread.stopThread(); 
     progressThread = null; 
    } 
} 
+0

Никогда не называйте свинг код отключения [EDT] (http://en.wikipedia.org/wiki/ Event_dispatching_thread). – predi

+0

См. [Этот ответ] (http://stackoverflow.com/questions/8916721/java-swing-update-label/8917565#8917565) для примера – Robin

+0

Похоже, вам нужен [ProgressMonitor] (http: // docs. oracle.com/javase/7/docs/api/javax/swing/ProgressMonitor.html), с некоторыми [примерами использования] (http://docs.oracle.com/javase/tutorial/uiswing/components/ progress.html) –

ответ

8

Но это затрудняет достижение этого, потому что после появления JDialog он не показывает никаких компонентов (включая JProgressBar) до тех пор, пока не будет выполнена логика основного потока (SwingUtilities).

у вас есть проблемы с Concurrency in Swing, Swing однопоточен и все обновления должны быть сделаны на EventDispatchThread, есть два способа

  • easies для использования Runnable#Thread, но выход в GUI свинга должен быть обернут в invokeLater

  • использования SwingWorker, пример про SwingWorker в оракулах JProgressBar и SwingWorker учебника

EDIT

этот код симулировать нарушение EDT и правильный обходной путь для SwingWorker слишком

import java.awt.Dimension; 
import java.awt.Toolkit; 
import java.awt.Window; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.beans.PropertyChangeEvent; 
import java.beans.PropertyChangeListener; 

import javax.swing.*; 

public class TestProgressBar { 

    private static void createAndShowUI() { 
     JFrame frame = new JFrame("TestProgressBar"); 
     frame.getContentPane().add(new TestPBGui().getMainPanel()); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     java.awt.EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       createAndShowUI(); 
      } 
     }); 
    } 

    private TestProgressBar() { 
    } 
} 

class TestPBGui { 

    private JPanel mainPanel = new JPanel(); 

    public TestPBGui() { 
     JButton yourAttempt = new JButton("Your attempt to show Progress Bar"); 
     JButton myAttempt = new JButton("My attempt to show Progress Bar"); 
     yourAttempt.addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       yourAttemptActionPerformed(); 
      } 
     }); 
     myAttempt.addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       myAttemptActionPerformed(); 
      } 
     }); 
     mainPanel.add(yourAttempt); 
     mainPanel.add(myAttempt); 
    } 

    private void yourAttemptActionPerformed() { 
     Window thisWin = SwingUtilities.getWindowAncestor(mainPanel); 
     JDialog progressDialog = new JDialog(thisWin, "Uploading..."); 
     JPanel contentPane = new JPanel(); 
     contentPane.setPreferredSize(new Dimension(300, 100)); 
     JProgressBar bar = new JProgressBar(0, 100); 
     bar.setIndeterminate(true); 
     contentPane.add(bar); 
     progressDialog.setContentPane(contentPane); 
     progressDialog.pack(); 
     progressDialog.setLocationRelativeTo(null); 
     Task task = new Task("Your attempt"); 
     task.execute(); 
     progressDialog.setVisible(true); 
     while (!task.isDone()) { 
     } 
     progressDialog.dispose(); 
    } 

    private void myAttemptActionPerformed() { 
     Window thisWin = SwingUtilities.getWindowAncestor(mainPanel); 
     final JDialog progressDialog = new JDialog(thisWin, "Uploading..."); 
     JPanel contentPane = new JPanel(); 
     contentPane.setPreferredSize(new Dimension(300, 100)); 
     final JProgressBar bar = new JProgressBar(0, 100); 
     bar.setIndeterminate(true); 
     contentPane.add(bar); 
     progressDialog.setContentPane(contentPane); 
     progressDialog.pack(); 
     progressDialog.setLocationRelativeTo(null); 
     final Task task = new Task("My attempt"); 
     task.addPropertyChangeListener(new PropertyChangeListener() { 

      @Override 
      public void propertyChange(PropertyChangeEvent evt) { 
       if (evt.getPropertyName().equalsIgnoreCase("progress")) { 
        int progress = task.getProgress(); 
        if (progress == 0) { 
         bar.setIndeterminate(true); 
        } else { 
         bar.setIndeterminate(false); 
         bar.setValue(progress); 
         progressDialog.dispose(); 
        } 
       } 
      } 
     }); 
     task.execute(); 
     progressDialog.setVisible(true); 
    } 

    public JPanel getMainPanel() { 
     return mainPanel; 
    } 
} 

class Task extends SwingWorker<Void, Void> { 

    private static final long SLEEP_TIME = 4000; 
    private String text; 

    public Task(String text) { 
     this.text = text; 
    } 

    @Override 
    public Void doInBackground() { 
     setProgress(0); 
     try { 
      Thread.sleep(SLEEP_TIME);// imitate a long-running task 
     } catch (InterruptedException e) { 
     } 
     setProgress(100); 
     return null; 
    } 

    @Override 
    public void done() { 
     System.out.println(text + " is done"); 
     Toolkit.getDefaultToolkit().beep(); 
    } 
} 
+0

+1! Хороший совет. – GETah

+0

Хороший пример, +1 – tenorsax

+0

@Max thanks, true - один из настоящих гуру Свинг (на этом форуме) напишите мне код similair как ответ на мой вопрос (другой форум) – mKorbel

1

Показать индикатор в главном потоке (где все ваши качели материал собирается на), и сделать интенсивный фон работать над отдельной нитью.

Пользовательский интерфейс будет реагировать все время (так как вы не блокируете основной поток), и вы можете уведомить его, когда вы выполняете длительную задачу.

+0

Просьба указать, что основной поток - это событие «Диспетчер событий», так как все компоненты Swing должны быть доступны в этом потоке (который отличается от потока, в котором выполняется ваш основной метод) – Robin