简体   繁体   中英

Why is SwingWorker not returning an object to the EDT?

I am using the SwingWorker class to perform a background task. Many different components of the GUI get updated after the background thread has done is job (these are in the done() method). The doInBackground() method publishes a HeatMap class object and the process() method adds it to a JPanel component. I have added MouseListener and MouseMotionListener to this Heatmap class object. The mouseMoved() method is present in the main GUI class. When the mouse is moved, the coordinate position of the mouse on the HeatMap should be displayed about it in a JLabel .

When I run the code, the HeatMap object is visible in the JPanel , but I think the EDT does not have access to it. This because, on a quick check I found out that the rawIntensityMap HeatMap object is not null in the process() method of the SwingWorker , but it is still null in the mouseMoved() method, due to which I get a NullPointerException .

The HeatMap object in the GUIMain class and the SwingWorker class have been declared as:

private HeatMap rawIntensityMap = null;

I do not send the rawIntensityMap object to the SwingWorker class constructor. I had tried that earlier but it did not work.

Here is the process() method from the SwingWorker class:

 @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);
        }
    });

    }

Here is the mouseMoved() method:

@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();
        }
    }

Here is the basic structure of my 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);
}


}

}

Can someone point at the error here?

SOME MORE CODE:

This is my GUIMain class where HeatMap rawIntensityMap is declared. Also, I have pasted parts of the code where this HeatMap object is actually used (have not pasted all the methods).

    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();
            }
        }

    }

The code from the SwingWorker class is already pasted above.

You have two completely separate fields named rawIntensityMap .

You have GUIMain.rawIntensityMap and FileReadWorker.rawIntensityMap . You assign FileReadWorker.rawIntensityMap in FileReadWorker::doInBackground , but you never assign GUIMain.rawIntensityMap to any value.

Try creating a setter for rawIntensityMap in GUIMain and calling guiClassObject.setRawIntensityMap(rawIntensityMap); in FileReadWorker::done .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM