0

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 MouseListenerand 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.

novicegeek
  • 773
  • 2
  • 9
  • 29
  • 2
    Complete examples are seen [here](http://stackoverflow.com/a/25043676/230513) and [here](http://stackoverflow.com/a/16880714/230513). – trashgod May 05 '16 at 16:05

1 Answers1

2

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.

Jeffrey
  • 44,417
  • 8
  • 90
  • 141
  • I tried using `volatile`, but it does not solve the issue. I made this declaration - `volatile HeatMap rawIntensityMap;` in both the `GUIMain` class and the `SwingWorker` class. For the complicated fix, should I declare `Heatmap heatmap` in the `GUIMain` class and make changes in the `mouseMoved` method? I did not quite understand what changes to be made? I would like to try this fix first and if it does not solve the issue, then I will provide a minimal example (since I will take time to write one. Have not done it earlier). – novicegeek May 05 '16 at 18:18
  • @novicegeek I'm confused. You have two different fields named `rawIntensityMap`? – Jeffrey May 05 '16 at 18:27
  • No. I have a class `GUIMain` where `HeatMap rawIntensityMap` is declared. Earlier I had tried to pass this `HeatMap` object to the `constructor` of my `SwingWorker` class. I also have a `HeatMap` object of the same name in the have this `SwingWorker`. In either cases, I get a `NullPointerException` when I try to access `rawIntensityMap` again after the background thread has finished executing. Is this the wrong way to do? – novicegeek May 05 '16 at 18:36
  • @novicegeek Can you post more of your code? Do you ever assign `GUIMain.rawIntensityMap` to anything? – Jeffrey May 05 '16 at 18:37
  • I have added more code snippets related to the `HeatMap` object used in the `GUIMain` class and also the `done()` method of the `SwingWorker` class is updated with code for the `MouseListener`. I very much appreciate your help with this issuse. Thank you – novicegeek May 05 '16 at 18:59
  • @novicegeek See my edit. I still don't know if that's the right answer because you haven't posted all of your code in a coherent manner. I can't tell where the `FileReadWorker`'s fields are declared. – Jeffrey May 05 '16 at 19:43
  • The setter method works :) I now get the coordinate values displayed and also the change in color gradient works. A big thank you. – novicegeek May 05 '16 at 20:10
  • I am facing a similar issue again, tried `get()` and `set()` methods but they do not help. May be you have some suggestion for me here: http://stackoverflow.com/questions/37226435/jpanel-with-a-specific-jradiobutton-does-not-update-after-getting-result-from-sw?noredirect=1#comment61982768_37226435 – novicegeek May 14 '16 at 12:07