2016-05-05 20 views
0

我正在使用SwingWorker类来执行后台任务。后台线程完成作业后,会更新GUI的许多不同组件(这些位于done()方法中)。 doInBackground()方法发布HeatMap类对象,而process()方法将其添加到JPanel组件。我已将MouseListenerMouseMotionListener添加到此Heatmap类对象。主要的GUI类中存在mouseMoved()方法。当移动鼠标时,应该在JLabel中显示关于它的HeatMap上的鼠标的坐标位置。SwingWorker为什么不将对象返回给EDT?

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

HeatMap对象在GUIMain类和SwingWorker类被声明为:

private HeatMap rawIntensityMap = null; 

我没有在rawIntensityMap对象发送到SwingWorker类的构造函数。我早些时候尝试过,但没有奏效。

下面是从SwingWorkerprocess()方法:

@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类的代码已经粘贴在上面。

+2

完整的示例见[这里](http://stackoverflow.com/a/25043676/230513)和[这里](http://stackoverflow.com/a/16880714/230513)。 – trashgod

回答

2

您有两个完全分开的字段,名称为rawIntensityMap

您有GUIMain.rawIntensityMapFileReadWorker.rawIntensityMap。您在FileReadWorker::doInBackground中指定FileReadWorker.rawIntensityMap,但您从未将GUIMain.rawIntensityMap指定为任何值。

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

+0

我试过用'volatile',但是没有解决问题。我在'GUIMain'类和'SwingWorker'类中都做了这个声明 - 'volatile HeatMap rawIntensityMap'。对于复杂的修复,我应该在'GUIMain'类中声明'Heatmap heatmap',并在'mouseMoved'方法中进行修改?我不太明白要做什么改变?我想先尝试这种修复方法,如果它不能解决问题,那么我会提供一个最简单的例子(因为我会花时间写一个,以前没做过)。 – novicegeek

+0

@novicegeek我很困惑。你有两个名为'rawIntensityMap'的不同字段? – Jeffrey

+0

不,我有一个'GUIMain'类声明'HeatMap rawIntensityMap'。之前我曾尝试将此'HeatMap'对象传递给我的'SwingWorker'类的'构造函数'。我在这个'SwingWorker'中也有一个同名的'HeatMap'对象。在任何一种情况下,当我在后台线程执行完毕后再次尝试访问'rawIntensityMap'时,我会得到'NullPointerException'。这是错误的方法吗? – novicegeek

相关问题