2016-05-05 43 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

相關問題