我如何使我的SwingWorker示例正常工作?
我已经创build了自己的SwingWorker示例来熟悉它的工作原理。
我想要做的是以下几点:当button被点击时,我想要一个进度条出现,直到任务完成我只想删除进度条,并添加一个string到对话框。
点击button时,进度条出现,但永远不会消失。 (从不删除进度条10秒后,永远不会放置标签)
这是一个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<Integer, Integer> { /* * 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); } }
这里是你的代码的更新版本
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<Integer, Integer> { /* * 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(); } }
关键点是设置一个模型对话框可见块直到对话框被丢弃。 所以当你切换组件的时候,使它成为非模态的,修正了它在内容窗格上的validate
调用。 我还调整了在EDT上运行的主要方法,并添加了一些System.out调用。 如果您删除了setModal( false )
调用,将会看到这些语句直到closures对话框才会被打印出来
没有必要使对话非模态化。 在启动SwingWorker后只需显示对话框。 这可以从调用类(执行SwingWorker的类)中完成,首先调用execute,然后显示对话框,或者可以从SwingWorker完成,但是如果来自后者,则必须创build自己的调用超级执行的伪执行方法,然后显示对话框。 请注意,你不能覆盖execute()本身,因为它是最终的。
例如…
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<Integer, Integer> { 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; } }