为什么 SwingWorker 不向 EDT 返回对象?

Why is SwingWorker not returning an object to the EDT?

我正在使用 SwingWorker class 执行后台任务。 GUI 的许多不同组件在后台线程完成工作后得到更新(这些在 done() 方法中)。 doInBackground() 方法发布一个 HeatMap class 对象,process() 方法将它添加到 JPanel 组件。我已将 MouseListenerMouseMotionListener 添加到此 Heatmap class 对象。 mouseMoved() 方法存在于主 GUI class 中。鼠标移动时,鼠标在HeatMap上的坐标位置应该显示在JLabel.

左右

当我 运行 代码时,HeatMap 对象在 JPanel 中可见,但我认为 EDT 无法访问它。这是因为,在快速检查中我发现 rawIntensityMap HeatMap 对象不是 SwingWorkerprocess() 方法中的 null,但它仍然是nullmouseMoved() 方法中,因此我得到了 NullPointerException.

GUIMain class 和 SwingWorker class 中的 HeatMap 对象已声明为:

private HeatMap rawIntensityMap = null;

我没有将 rawIntensityMap 对象发送给 SwingWorker class 构造函数。我之前曾尝试过,但没有用。

这是 SwingWorker class 中的 process() 方法:

 @Override
protected void process(List<HeatMap> chunks) {

    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            imagePanel.add(rawIntensityMap, BorderLayout.CENTER);
            coordinates.setBounds(31, 31, rawIntensityMap.getWidth() - 31, rawIntensityMap.getHeight() - 31);
        }
    });

    }

这里是mouseMoved()方法:

@Override
    public void mouseMoved(MouseEvent e) {
        System.out.println("I am in the mouseevent" + coordinates.toString());
        System.out.println("Width of raw Intensity map: " + rawIntensityMap.getWidth());
        if (e.getPoint().x >= 31 && e.getPoint().y >= 31 && e.getPoint().x <= rawIntensityMap.getWidth() - 31 && e.getPoint().y <= rawIntensityMap.getHeight() - 31) {
            rawIntensityMap.removeAll();
            rawIntensityMap.add(coordinates);
            coordinates.setText("(x,y) = " + "(" + (e.getPoint().x - 31) + "," + (e.getPoint().y - 31) + ")");
            if (peakPickedImage.isSelected()) {
                preprocessedIntensityMap.add(coordinates);
                coordinates.setText("(x,y) = " + "(" + (e.getPoint().x - 31) + "," + (e.getPoint().y - 31) + ")");
                coordinates.revalidate();
                coordinates.repaint();
            }
            coordinates.revalidate();
            coordinates.repaint();
        }
    }

这是我的基本结构 SwingWorker Class:

public class FileReadWorker extends SwingWorker<REXP, HeatMap> {

 public FileReadWorker(GUIMain guiClassObject, File fileName, JTree rawSpectraTree, DefaultTreeModel model, DefaultMutableTreeNode root, String currentPath, JTextField minMz, JTextField maxMz, JFreeChart spectrumPlot, ChartPanel chartPanel, JPanel chartContent, float minMzValue, float maxMzValue, Float globalMinMz, Float globalMaxMz, JLabel statusLabel, JPanel imagePanel, JLabel coordinates, JTabbedPane tabbedSpectralFiles, JScrollPane spectralFilesScrollPane, JPanel rawFilesPanel, JRadioButton rawImage, JRadioButton peakPickedImage, JMenuItem loadPeakListMenuItem, JButton loadPeaklistsButton, JMenuItem propertiesMenuItem, JButton propertiesButton) {
        this.guiClassObject = guiClassObject;
        this.fileName = fileName;
        this.rawSpectraTree = rawSpectraTree;
        this.currentPath = currentPath;
        this.minMz = minMz;
        this.maxMz = maxMz;
        this.spectrumPlot = spectrumPlot;
        this.chartPanel = chartPanel;
        this.chartContent = chartContent;
        this.minMzValue = minMzValue;
        this.maxMzValue = maxMzValue;
        this.GlobalMinMz = globalMinMz;
        this.GlobalMaxMz = globalMaxMz;
        this.statusLabel = statusLabel;
        this.imagePanel = imagePanel;
        this.coordinates = coordinates;
        this.tabbedSpectralFiles = tabbedSpectralFiles;
        this.spectralFilesScrollPane = spectralFilesScrollPane;
        this.rawFilesPanel = rawFilesPanel;
        this.rawImage = rawImage;
        this.peakPickedImage = peakPickedImage;
        this.loadPeakListMenuItem = loadPeakListMenuItem;
        this.loadPeaklistsButton = loadPeaklistsButton;
        this.propertiesMenuItem = propertiesMenuItem;
        this.propertiesButton = propertiesButton;
        this.model = model;
        this.root = root;
    }

@Override
    protected REXP doInBackground() throws Exception {

// does some background tasks

// Works on the generating the HeatMap

try {
            rawIntensityMap = gim.generateIntensityMap(rawSpectrumObjects, currentPath, minMzValue, maxMzValue, Gradient.GRADIENT_Rainbow, "RAW");
            publish(rawIntensityMap);
        } catch (RserveException e) {
            e.printStackTrace();
        } catch (REXPMismatchException e) {
            e.printStackTrace();
        }

// returns a REXP object
        return rawSpectrumObjects;
    }

  @Override
    public void done() {

// Updates different components of the GUI
rawIntensityMap.addMouseListener(guiClassObject);
        rawIntensityMap.addMouseMotionListener(guiClassObject);
}


}

}

有人可以指出这里的错误吗?

更多代码:

这是我的 GUIMain class,其中声明了 HeatMap rawIntensityMap。此外,我粘贴了实际使用此 HeatMap 对象的部分代码(未粘贴所有方法)。

    public class GUIMain extends JFrame implements ActionListener, ItemListener, MouseListener, MouseMotionListener, ChangeListener {

    volatile HeatMap rawIntensityMap;
private JPanel imagePanel; // container for the HeatMap


 /**
     * Constructor to setup the GUI
     */
    public GUIMain(String title) {

        super(title);

        setLayout(new BorderLayout());
        //getSize();
        setSize(getSize());

 imagePanel = new JPanel(new BorderLayout());
        g.gridx = 0;
        g.gridy = 1;
        g.gridwidth = 2;
        g.weightx = 1.0; // fill the rest of the space
        g.weighty = 1.0;
        g.fill = GridBagConstraints.BOTH;

        imagePanel.setBorder(BorderFactory.createEtchedBorder());
        //imagePanel.addMouseListener(this);

        imageDisplay.add(imagePanel, g);
        //  ImageDisplay.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));

        imageDisplay.setBorder(
                BorderFactory.createCompoundBorder(
                        BorderFactory.createTitledBorder("View 2-D ion intensity map"),
                        BorderFactory.createEmptyBorder(5, 5, 5, 5)));

}

public void actionPerformed(ActionEvent e) {

        //Handle open *.img imaging file button and menu item action

        if ((e.getSource() == OpenImagingFileButton) || (e.getSource() == loadRawSpectraMenuItem)) {
            int returnVal = fcImg.showOpenDialog(GUIMain.this);

            if (returnVal == JFileChooser.APPROVE_OPTION) {
                file = fcImg.getSelectedFile();

                root = new DefaultMutableTreeNode(file);
                rawSpectraTree = new JTree(root);
                model = (DefaultTreeModel) rawSpectraTree.getModel();

    //Passing this HeatMap to the SwingWorker class

    FileReadWorker frw = new FileReadWorker(this, file, rawSpectraTree, rawIntensityMap, model, root, currentPath, minMz, maxMz, spectrumPlot, chartPanel, chartContent, minMzValue, maxMzValue, GlobalMinMz, GlobalMaxMz, statusLabel, imagePanel, coordinates, tabbedSpectralFiles, spectralFilesScrollPane, rawFilesPanel, rawImage, peakPickedImage, loadPeakListMenuItem, loadPeaklistsButton, propertiesMenuItem, propertiesButton);
                    frw.execute();

}


    // Method when a different HeatMap color gradient is selected
    @Override
        public void itemStateChanged(ItemEvent e) {
            colorNumber = (Integer) e.getItem();
            if (e.getStateChange() == ItemEvent.SELECTED) {
                rawIntensityMap.updateGradient(gradients[colorNumber]);
                if (peakPickedImage.isEnabled()) {
                    preprocessedIntensityMap.updateGradient(gradients[colorNumber]);
                }
            }

        }

    // Mouse moved event

     @Override
        public void mouseMoved(MouseEvent e) {
            if(rawIntensityMap == null)
                System.out.println("TRUE**");
            else
                System.out.println("FALSE**");
            System.out.println("I am in the mouseevent" + coordinates.toString());
            if (e.getPoint().x >= 31 && e.getPoint().y >= 31 && e.getPoint().x <= rawIntensityMap.getWidth() - 31 && e.getPoint().y <= rawIntensityMap.getHeight() - 31) {
                rawIntensityMap.removeAll();
                rawIntensityMap.add(coordinates);
                coordinates.setText("(x,y) = " + "(" + (e.getPoint().x - 31) + "," + (e.getPoint().y - 31) + ")");
                if (peakPickedImage.isSelected()) {
                    preprocessedIntensityMap.add(coordinates);
                    coordinates.setText("(x,y) = " + "(" + (e.getPoint().x - 31) + "," + (e.getPoint().y - 31) + ")");
                    coordinates.revalidate();
                    coordinates.repaint();
                }
                coordinates.revalidate();
                coordinates.repaint();
            }
        }

    }

SwingWorker class 中的代码已粘贴在上面。

您有两个完全独立的字段,名为 rawIntensityMap

您有 GUIMain.rawIntensityMapFileReadWorker.rawIntensityMap。您在 FileReadWorker::doInBackground 中分配了 FileReadWorker.rawIntensityMap,但您从未将 GUIMain.rawIntensityMap 分配给任何值。

尝试在 GUIMain 中为 rawIntensityMap 创建一个 setter 并在 FileReadWorker::done 中调用 guiClassObject.setRawIntensityMap(rawIntensityMap);