问题
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.
回答1:
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
.
来源:https://stackoverflow.com/questions/37054780/why-is-swingworker-not-returning-an-object-to-the-edt