如何从SwingWorker类返回值并在其他类中使用并在进程完成时启用MenuItem?

我正在使用SwingWorker类使进程在另一个线程中运行。 我想要的是,一旦这个线程完成处理,它应该返回一个String ,它也应该启用一个JMenuItem 。 我在SwingWorker类中使用done()方法来启用JMenuItem但是我收到了NullPinterExceptiondoInBackground()方法返回一个我想在主GUI类中访问的String – GUIMain.java ,它存在于同一个包中。 我该怎么做? 我看到很多实现done()onPostExecute()方法的例子,但我想我在某个地方出错了。 这是我实现的代码:

  public class GUIMain extends JFrame implements ActionListener, FocusListener, ItemListener, MouseListener, MouseMotionListener { private JMenuBar menuBar; // Defined a menuBar item private JMenu recalibrationMenu; // Define the recalibration menu item private JMenuItem CGMenuItem; private JMenuItem TGMenuItem; private JMenu viewResultsMenu; // Define the View Results menu item public JMenuItem cgResults; public JMenuItem tgResults; private JPanel TGImage; private JPanel TGPanel; private JPanel CGImage; private JPanel CGPanel; private JPanel CGRecalibrationParameters; private JDialog resultsParameters; private JLabel massPeakLabel = new JLabel("Select mass peak (m/z)"); private JTextField massPeakField = new JTextField(5); private JLabel massWindowLabel = new JLabel("Mass window (Da)"); private JTextField massWindowField = new JTextField(5); private float mzPeakValue; private float massWindowValue; private JButton massPeakSelectionButton = new JButton("OK"); private JButton CloseDialogButton = new JButton("Cancel"); private String CGRecalibratedFilesPath; private String TGRecalibratedFilesPath; /** Constructor to setup the GUI */ public GUIMain(String title) { super(title); setLayout(new BorderLayout()); menuBar = new JMenuBar(); menuBar.setBorder(new BevelBorder(BevelBorder.RAISED)); // build the Recalibration menu recalibrationMenu = new JMenu("Recalibration"); CGMenuItem = new JMenuItem("Crystal Growth"); CGMenuItem.setEnabled(false); //initially disabled when app is launched CGMenuItem.addActionListener(this); TGMenuItem = new JMenuItem("Topological Greedy"); TGMenuItem.setEnabled(false); //initially disabled when app is launched TGMenuItem.addActionListener(this); recalibrationMenu.add(CGMenuItem); recalibrationMenu.add(TGMenuItem); // build the View Results menu viewResultsMenu = new JMenu("View Results"); cgResults = new JMenuItem("CG Recalibration"); cgResults.setEnabled(false); //initially disabled when app is launched cgResults.addActionListener(this); tgResults = new JMenuItem("TG Recalibration"); tgResults.setEnabled(false); //initially disabled when app is launched tgResults.addActionListener(this); viewResultsMenu.add(cgResults); viewResultsMenu.add(tgResults); // add menus to menubar menuBar.add(fileMenu); menuBar.add(recalibrationMenu); menuBar.add(viewResultsMenu); // put the menubar on the frame setJMenuBar(menuBar); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Exit program if close-window button clicked setPreferredSize(new Dimension(1300, 800)); // Set the preferred window size pack(); setLocationRelativeTo(null); setVisible(true); } public GUIMain() { } } public void actionPerformed(ActionEvent e) { //Handle CG menu item action **if ((e.getSource() == CGMenuItem)) { RecalibrationWorker rw = new RecalibrationWorker(file,"CG"); rw.processCompleted(); rw.setVisible(true); cgResults.setEnabled(true); }** if ((e.getSource() == cgResults)) { viewRecalibrationResults("CG Recalibration - View Results", "CG"); } if ((e.getSource() == tgResults)) { viewRecalibrationResults("TG Recalibration - View Results", "TG"); } } private void viewRecalibrationResults(String dialogTitle, final String recalibrationType) { resultsParameters = new JDialog(); resultsParameters.setLayout(new GridBagLayout()); resultsParameters.setTitle(dialogTitle); GridBagConstraints gc = new GridBagConstraints(); gc.gridx = 0; gc.gridy = 0; gc.anchor = GridBagConstraints.WEST; gc.ipady = 20; // gc.anchor = GridBagConstraints.WEST; resultsParameters.add(massPeakLabel, gc); commonMassThresholdLabel.setLabelFor(massPeakField); gc.gridx = 1; gc.gridy = 0; gc.ipady = 0; gc.anchor = GridBagConstraints.CENTER; resultsParameters.add(massPeakField,gc); massPeakField.setText(""); massPeakField.addActionListener(this); massPeakField.addFocusListener(this); gc.gridx = 0; gc.gridy = 1; gc.ipady = 20; gc.anchor = GridBagConstraints.WEST; resultsParameters.add(massWindowLabel, gc); massWindowLabel.setLabelFor(massWindowField); gc.gridx = 1; gc.gridy = 1; gc.ipady = 0; gc.anchor = GridBagConstraints.CENTER; resultsParameters.add(massWindowField,gc); massWindowField.setText(""); massWindowField.addActionListener(this); massWindowField.addFocusListener(this); gc.gridx = 0; gc.gridy = 2; gc.anchor = GridBagConstraints.CENTER; resultsParameters.add(massPeakSelectionButton, gc); massPeakSelectionButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if ("CG".equals(recalibrationType)) recalibrationResults("CG"); else if ("TG".equals(recalibrationType)) recalibrationResults("TG"); } }); massPeakSelectionButton.addKeyListener(new KeyListener() { @Override public void keyTyped(KeyEvent e) { } @Override public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ENTER) { if ("CG".equals(recalibrationType)) recalibrationResults("CG"); else if ("TG".equals(recalibrationType)) recalibrationResults("TG"); } } @Override public void keyReleased(KeyEvent e) { } }); gc.gridx = 1; gc.gridy = 2; gc.anchor = GridBagConstraints.EAST; resultsParameters.add(CloseDialogButton,gc); CloseDialogButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { resultsParameters.dispose(); } }); resultsParameters.setVisible(true); resultsParameters.setLocationRelativeTo(this); resultsParameters.setSize(270, 150); resultsParameters.setResizable(false); } } public class RecalibrationWorker extends JDialog { private boolean isStarted = false; private JLabel counterLabel = new JLabel("Recalibration not yet started"); private Worker worker = new Worker(); private JPanel recalibrationParameters; private ButtonGroup radioButtonGroup = new ButtonGroup(); private JRadioButton rawSpectra = new JRadioButton("Use raw spectra"); private JRadioButton preprocessedSpectra = new JRadioButton("Use preprocessed spectra"); private static float commonMassThresholdValue; private static float recalibrationThresholdValue; private static double mergeSpectraThresholdValue; private JLabel commonMassThresholdLabel = new JLabel("Common Mass Window
(value between 0.01-0.9 Da)"); private JTextField commonMassThresholdField = new JTextField(String.valueOf(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { commonMassThresholdValue = Float.parseFloat(commonMassThresholdField.getText()); recalibrationThresholdField.requestFocusInWindow(); } })); private JLabel recalibrationThresholdLabel = new JLabel("Mass threshold to recalibrate two spectra
(value between 0.01-0.9 Da)"); private JTextField recalibrationThresholdField = new JTextField(String.valueOf(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { recalibrationThresholdValue = Float.parseFloat(recalibrationThresholdField.getText()); mergeSpectraThresholdField.requestFocusInWindow(); } })); private JLabel mergeSpectraThresholdLabel = new JLabel("Mass threshold to merge spectra
(value between 0.01-0.9 Da)"); private JTextField mergeSpectraThresholdField= new JTextField(String.valueOf(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { mergeSpectraThresholdValue = Float.parseFloat(mergeSpectraThresholdField.getText()); startButton.requestFocusInWindow(); } })); private JTextArea recalibrationStatus = new JTextArea(7,32); private JScrollPane textAreaScrolling = new JScrollPane(recalibrationStatus); private JButton startButton = new JButton(new AbstractAction("Recalibrate") { @Override public void actionPerformed(ActionEvent arg0) { if(!isStarted) { Worker w = new Worker(); w.addPropertyChangeListener(new RecalibrationWorkerPropertyHandler(RecalibrationWorker.this)); w.execute(); isStarted = false; } } }); private JButton stopButton = new JButton(new AbstractAction("Stop") { @Override public void actionPerformed(ActionEvent arg0) { worker.cancel(true); } }); public File file; public String type; public String resultFilePath; public RecalibrationWorker(File dataFile, String recalibrationType) { file = dataFile; type = recalibrationType; setLayout(new GridBagLayout()); if("CG".equals(recalibrationType)) setTitle("Crystal Growth Recalibration"); else if("TG".equals(recalibrationType)) setTitle("Topological Greedy Recalibration"); recalibrationParameters = new JPanel(new GridBagLayout()); GridBagConstraints gc = new GridBagConstraints(); radioButtonGroup.add(rawSpectra); radioButtonGroup.add(preprocessedSpectra); gc.gridx = 0; gc.gridy = 0; gc.anchor = GridBagConstraints.WEST; recalibrationParameters.add(preprocessedSpectra,gc); gc.gridx = 1; gc.gridy = 0; recalibrationParameters.add(rawSpectra,gc); gc.gridx = 0; gc.gridy = 1; gc.ipady = 20; gc.anchor = GridBagConstraints.WEST; recalibrationParameters.add(commonMassThresholdLabel, gc); commonMassThresholdLabel.setLabelFor(commonMassThresholdField); commonMassThresholdField.setColumns(3); commonMassThresholdField.setText(""); gc.gridx = 1; gc.gridy = 1; gc.ipady = 0; gc.anchor = GridBagConstraints.CENTER; recalibrationParameters.add(commonMassThresholdField, gc); commonMassThresholdField.addFocusListener(new FocusListener() { @Override public void focusGained(FocusEvent e) { } @Override public void focusLost(FocusEvent e) { commonMassThresholdValue = Float.parseFloat(commonMassThresholdField.getText()); recalibrationThresholdField.requestFocusInWindow(); } }); gc.gridx = 0; gc.gridy = 2; gc.ipady = 20; gc.anchor = GridBagConstraints.WEST; recalibrationParameters.add(recalibrationThresholdLabel, gc); recalibrationThresholdLabel.setLabelFor(recalibrationThresholdField); recalibrationThresholdField.setColumns(3); recalibrationThresholdField.setText(""); gc.gridx = 1; gc.gridy = 2; gc.ipady = 0; gc.anchor = GridBagConstraints.CENTER; recalibrationParameters.add(recalibrationThresholdField, gc); recalibrationThresholdField.addFocusListener(new FocusListener() { @Override public void focusGained(FocusEvent e) { } @Override public void focusLost(FocusEvent e) { recalibrationThresholdValue = Float.parseFloat(recalibrationThresholdField.getText()); mergeSpectraThresholdField.requestFocusInWindow(); } }); gc.gridx = 0; gc.gridy = 3; gc.ipady = 20; gc.anchor = GridBagConstraints.WEST; recalibrationParameters.add(mergeSpectraThresholdLabel, gc); mergeSpectraThresholdLabel.setLabelFor(mergeSpectraThresholdField); mergeSpectraThresholdField.setText(""); gc.gridx = 1; gc.gridy = 3; gc.ipady = 0; gc.anchor = GridBagConstraints.CENTER; recalibrationParameters.add(mergeSpectraThresholdField, gc); mergeSpectraThresholdField.setColumns(3); mergeSpectraThresholdField.addFocusListener(new FocusListener() { @Override public void focusGained(FocusEvent e) { } @Override public void focusLost(FocusEvent e) { mergeSpectraThresholdValue = Double.parseDouble(mergeSpectraThresholdField.getText()); startButton.requestFocusInWindow(); } }); recalibrationParameters.setBorder( BorderFactory.createCompoundBorder( BorderFactory.createTitledBorder("Parameters"), BorderFactory.createEmptyBorder(5, 5, 5, 5))); gc.gridx = 0; gc.gridy = 4; gc.anchor = GridBagConstraints.EAST; recalibrationParameters.add(startButton, gc); gc.gridx = 1; gc.gridy = 4; gc.anchor = GridBagConstraints.WEST; recalibrationParameters.add(stopButton, gc); gc.gridx = 0; gc.gridy = 0; gc.anchor = GridBagConstraints.CENTER; add(recalibrationParameters, gc); textAreaScrolling.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createTitledBorder("Recalibration status"), BorderFactory.createEmptyBorder(5, 5, 5, 5))); gc.gridx = 0; gc.gridy = 1; gc.anchor = GridBagConstraints.CENTER; add(textAreaScrolling, gc); recalibrationStatus.setWrapStyleWord(true); recalibrationStatus.setLineWrap(true); recalibrationStatus.setEditable(false); setVisible(true); setLocationRelativeTo(this); setSize(415, 425); setResizable(false); pack(); setDefaultCloseOperation(DISPOSE_ON_CLOSE); } // constructor public RecalibrationWorker() { } public float commonMassThreshold() { return commonMassThresholdValue; } public float recalibrationThreshold() { return recalibrationThresholdValue; } public double mergeSpectraThreshold() { return mergeSpectraThresholdValue; } protected String processCompleted() { return resultFilePath; } protected void processFailed() { System.out.println("Recalibration failed"); } class Worker extends SwingWorker { // String resultfilePath; @Override public String doInBackground() throws Exception { InputData inputDataObject1 = new InputData(); if(type == "CG") { resultFilePath = inputDataObject1.startRecalibration(file, type); publish("Recalibration Successful!\nFiles can be found at: " + resultFilePath); } else if (type == "TG") { resultFilePath = inputDataObject1.startRecalibration(file, type); publish("Recalibration Successful!\nFiles can be found at: " + resultFilePath); } return resultFilePath; } public void done() { try { get(); } catch (Exception e) { } } @Override protected void process(java.util.List chunks) { String value = chunks.get(chunks.size() - 1); recalibrationStatus.append("\n"+value); // recalibrationStatus.append(chunks.toString()); } } import javax.swing.*; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.concurrent.ExecutionException; /** * Created by localadm on 27/09/15. */ public class RecalibrationWorkerPropertyHandler implements PropertyChangeListener { private RecalibrationWorker rwObject; public RecalibrationWorkerPropertyHandler(RecalibrationWorker rwObject) { this.rwObject = rwObject; } @Override public void propertyChange(PropertyChangeEvent evt) { // System.out.println(evt.getPropertyName()); if ("progress".equalsIgnoreCase(evt.getPropertyName())) { // int value = (int) evt.getNewValue(); // rwObject.showProgress(value); } else if ("state".equalsIgnoreCase(evt.getPropertyName())) { SwingWorker worker = (SwingWorker) evt.getSource(); if (worker.isDone()) { try { worker.get(); System.out.println("I am here"); rwObject.processCompleted(); } catch (InterruptedException exp) { rwObject.processFailed(); } catch (ExecutionException e) { rwObject.processFailed(); } } } } }

由于您使用的是JDialog来管理SwingWorker ,因此您可以实际使用对话框的模态状态。

实质上,当一个对话框是模态的时,它将阻止代码执行,使对话框可见。 它将一直阻塞,直到隐藏对话框,此时代码将继续执行。

因此,您可以在对话框可见之前禁用该按钮,并在关闭对话框时重新启用它。

工人

 import java.awt.Dimension; import java.awt.EventQueue; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.SwingUtilities; import javax.swing.SwingWorker; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class Test { public static void main(String[] args) { new Test(); } public Test() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new TestPane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class TestPane extends JPanel { public TestPane() { setLayout(new GridBagLayout()); JButton btn = new JButton("Go"); add(btn); btn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { btn.setEnabled(false); SomeWorkerDialog worker = new SomeWorkerDialog(TestPane.this); // This is just so we can see the button ;) Point point = btn.getLocationOnScreen(); worker.setLocation(worker.getX(), point.y + btn.getHeight()); worker.setVisible(true); btn.setEnabled(true); } }); } @Override public Dimension getPreferredSize() { return new Dimension(200, 200); } } public class SomeWorkerDialog extends JDialog { private JProgressBar progressBar; private SomeWorkerSomeWhere worker; public SomeWorkerDialog(JComponent parent) { super(SwingUtilities.getWindowAncestor(parent), "Working Hard", DEFAULT_MODALITY_TYPE); progressBar = new JProgressBar(); setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridwidth = GridBagConstraints.HORIZONTAL; gbc.weightx = 1; gbc.insets = new Insets(10, 10, 10, 10); add(progressBar, gbc); worker = new SomeWorkerSomeWhere(); worker.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { String name = evt.getPropertyName(); switch (name) { case "state": switch (worker.getState()) { case DONE: setVisible(false); break; } break; case "progress": progressBar.setValue(worker.getProgress()); break; } } }); addWindowListener(new WindowAdapter() { @Override public void windowOpened(WindowEvent e) { worker.execute(); } @Override public void windowClosed(WindowEvent e) { worker.cancel(true); } }); pack(); setLocationRelativeTo(parent); } } public class SomeWorkerSomeWhere extends SwingWorker { @Override protected Object doInBackground() throws Exception { for (int index = 0; index < 100 && !isCancelled(); index++) { setProgress(index); Thread.sleep(10); } return "AllDone"; } } } 

更新

要获取工作返回的值,可以在对话框中添加一个返回计算值的方法...

 public String getValue() throws Exception { return worker.get() } 

因此,一旦关闭对话框并继续执行代码,您就可以启用所需的组件并调用getValue方法

您还可以在状态更改并通知PropertyChangeListener时存储结果