Wie mache ich mein SwingWorker Beispiel richtig?

Ich habe mein eigenes SwingWorker-Beispiel erstellt, um mich mit der functionsweise vertraut zu machen.

Was ich tun möchte, ist folgendes: Wenn der Knopf angeklickt wird, möchte ich einen Fortschrittsbalken anzeigen, bis die Aufgabe erledigt ist. Ich möchte einfach den Fortschrittsbalken entfernen und eine Zeichenfolge zum Dialog hinzufügen.

Wenn Sie auf die Schaltfläche klicken, wird der Fortschrittsbalken angezeigt, verschwindet jedoch nicht. (Entfernt nie den Fortschrittsbalken nach 10 Sekunden und platziert das Label nie oben)

Hier ist ein SSCCE:

package swingtesting; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JProgressBar; import javax.swing.SwingWorker; public class SwingTesting { /** * Creates a frame that will hold a simple button to make use of SwingWorker */ public static void main(String[] args) { // TODO code application logic here JFrame frame = new JFrame(); JButton button = new JButton(); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { new GuiWorker().execute(); } }); button.setText("Test Me"); frame.getContentPane().add(button); frame.pack(); frame.setVisible(true); } } class GuiWorker extends SwingWorker { /* * This should just create a frame that will hold a progress bar until the * work is done. Once done, it should remove the progress bar from the dialog * and add a label saying the task complete. */ private JFrame frame = new JFrame(); private JDialog dialog = new JDialog(frame, "Swingworker test", true); private JProgressBar progressBar = new JProgressBar(); public GuiWorker() { progressBar.setString("Waiting on time"); progressBar.setStringPainted(true); progressBar.setIndeterminate(true); dialog.getContentPane().add(progressBar); dialog.pack(); dialog.setVisible(true); } @Override protected Integer doInBackground() throws Exception { Thread.sleep(10000); return 0; } @Override protected void done() { JLabel label = new JLabel("Task Complete"); dialog.getContentPane().remove(progressBar); dialog.getContentPane().add(label); } } 

Hier eine aktualisierte Version Ihres Codes, die funktioniert

 import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JProgressBar; import javax.swing.SwingWorker; public class SwingTesting { public static void main(String[] args) { EventQueue.invokeLater( new Runnable() { @Override public void run() { JFrame frame = new JFrame(); JButton button = new JButton(); button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { new GuiWorker().execute(); } }); button.setText("Test Me"); frame.getContentPane().add(button); frame.pack(); frame.setVisible(true); } } ); } } class GuiWorker extends SwingWorker { /* * This should just create a frame that will hold a progress bar until the * work is done. Once done, it should remove the progress bar from the dialog * and add a label saying the task complete. */ private JFrame frame = new JFrame(); private JDialog dialog = new JDialog(frame, "Swingworker test", true); private JProgressBar progressBar = new JProgressBar(); public GuiWorker() { progressBar.setString("Waiting on time"); progressBar.setStringPainted(true); progressBar.setIndeterminate(true); dialog.getContentPane().add(progressBar); dialog.pack(); dialog.setModal( false ); dialog.setVisible(true); } @Override protected Integer doInBackground() throws Exception { System.out.println( "GuiWorker.doInBackground" ); Thread.sleep(1000); return 0; } @Override protected void done() { System.out.println("done"); JLabel label = new JLabel("Task Complete"); dialog.getContentPane().remove(progressBar); dialog.getContentPane().add(label); dialog.getContentPane().validate(); } } 

Der entscheidende Punkt ist, dass ein Modell-Dialog so lange sichtbare Blöcke anzeigt, bis das Dialogfeld geöffnet wird. Wenn Sie es also nicht-modal machen, wurde der + validate Aufruf im Inhaltsbereich beim Wechseln der Komponenten korrigiert. Ich habe auch Ihre Hauptmethode für die Ausführung im EDT angepasst und einige System.out-Aufrufe hinzugefügt. Wenn Sie den setModal( false ) entfernen, werden diese statementen erst ausgedruckt, wenn Sie das Dialogfeld schließen

Der Dialog muss nicht modal sein. Zeigen Sie den Dialog nach dem Start des SwingWorker einfach an. Dies kann entweder von der aufrufenden class, der SwingWorker ausgeführt werden, indem zuerst execute aufgerufen wird, und dann den Dialog angezeigt wird, oder es kann aus dem SwingWorker gemacht werden, aber wenn aus letzterem, müssen Sie Ihre eigenen erstellen pseudo-execute-Methode, die die Ausführung von super aufruft und dann das Dialogfeld anzeigt. Beachten Sie, dass Sie execute () selbst nicht überschreiben können, da dies endgültig ist.

Beispielsweise…

 import java.awt.CardLayout; import java.awt.Window; import java.awt.Dialog.ModalityType; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.concurrent.ExecutionException; import javax.swing.*; @SuppressWarnings("serial") public class SwingTesting2 { private static void createAndShowGui() { final JFrame frame = new JFrame("SwingTesting2"); final JDialog dialog = new JDialog(frame, "Dialog", ModalityType.APPLICATION_MODAL); final DialogPanel dialogPanel = new DialogPanel(); dialog.getContentPane().add(dialogPanel.getMainPanel()); dialog.pack(); dialog.setLocationRelativeTo(frame); JButton button = new JButton(new AbstractAction("Test Me") { @Override public void actionPerformed(ActionEvent actEvt) { final GuiWorker2 guiWorker = new GuiWorker2(); guiWorker.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent pcEvt) { if (pcEvt.getPropertyName().equals("state")) { if (pcEvt.getNewValue() == SwingWorker.StateValue.DONE) { try { dialogPanel.done(guiWorker.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } } else if (pcEvt.getPropertyName().equals("progress")) { dialogPanel.setProgress((Integer)pcEvt.getNewValue()); } } }); guiWorker.execute(); dialogPanel.start(); dialog.setVisible(true); } }); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(button); frame.pack(); frame.setLocationByPlatform(true); frame.setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGui(); } }); } } class GuiWorker2 extends SwingWorker { private static final int MAX_COUNT = 20; private static final long SLEEP_TIME = 100; private int count = 0; @Override protected Integer doInBackground() throws Exception { while (count < MAX_COUNT) { Thread.sleep(SLEEP_TIME); count++; setProgress((100 * count) / MAX_COUNT); } return count; } } @SuppressWarnings("serial") class DialogPanel { public static final String PROGRESS_BAR = "Progress Bar"; public static final String DONE = "Done"; private static final int TIMER_DELAY = 2000; private CardLayout cardLayout = new CardLayout(); private JPanel mainPanel = new JPanel(cardLayout); private JLabel doneLabel = new JLabel("Done", JLabel.CENTER); private JProgressBar progressBar = new JProgressBar(); public DialogPanel() { progressBar.setString("Waiting on time"); progressBar.setStringPainted(true); progressBar.setIndeterminate(false); mainPanel.add(progressBar, PROGRESS_BAR); mainPanel.add(doneLabel, DONE); } public void setProgress(Integer newValue) { progressBar.setValue(newValue); } public void start() { cardLayout.show(mainPanel, PROGRESS_BAR); progressBar.setValue(0); } public void done(int countValue) { doneLabel.setText(DONE + ". Count: " + countValue); cardLayout.show(mainPanel, DONE); new Timer(TIMER_DELAY, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { Window win = SwingUtilities.getWindowAncestor(mainPanel); win.dispose(); } }){{setRepeats(false);}}.start(); } public JPanel getMainPanel() { return mainPanel; } }