我正在使用SwingWorker
类来执行后台任务。后台线程完成作业后,会更新GUI
的许多不同组件(这些位于done()
方法中)。 doInBackground()
方法发布HeatMap
类对象,而process()
方法将其添加到JPanel
组件。我已将MouseListener
和MouseMotionListener
添加到此Heatmap
类对象。主要的GUI类中存在mouseMoved()
方法。当移动鼠标时,应该在JLabel
中显示关于它的HeatMap
上的鼠标的坐标位置。SwingWorker为什么不将对象返回给EDT?
当我运行代码时,HeatMap
对象在JPanel
中可见,但我认为EDT
无法访问它。这是因为,在一个快速检查,我发现,在rawIntensityMap
HeatMap
对象不在SwingWorker
的process()
方法null
,但它仍然是null
在mouseMoved()
方法,因为我得到了NullPointerException
。
的HeatMap
对象在GUIMain
类和SwingWorker
类被声明为:
private HeatMap rawIntensityMap = null;
我没有在rawIntensityMap
对象发送到SwingWorker
类的构造函数。我早些时候尝试过,但没有奏效。
下面是从SwingWorker
类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
类的基本结构:
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
所在班级HeatMap rawIntensityMap
声明。另外,我粘贴了实际使用该对象的部分代码(未粘贴所有方法)。
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
类的代码已经粘贴在上面。
完整的示例见[这里](http://stackoverflow.com/a/25043676/230513)和[这里](http://stackoverflow.com/a/16880714/230513)。 – trashgod