2016-05-05 16 views
0

Ich verwende die SwingWorker Klasse, um eine Hintergrundaufgabe durchzuführen. Viele verschiedene Komponenten der GUI werden aktualisiert, nachdem der Hintergrund-Thread getan hat, ist Job (diese sind in der done() Methode). Die doInBackground()-Methode veröffentlicht ein Klassenobjekt HeatMap und die process()-Methode fügt es zu einer JPanel Komponente hinzu. Ich habe MouseListener und MouseMotionListener zu diesem Heatmap Klassenobjekt hinzugefügt. Die mouseMoved()-Methode ist in der Haupt-GUI-Klasse vorhanden. Wenn die Maus bewegt wird, sollte die Koordinatenposition der Maus auf dem HeatMap darüber in einem JLabel angezeigt werden.Warum gibt SwingWorker kein Objekt an den EDT zurück?

Wenn ich den Code ausführen, ist das HeatMap Objekt in der JPanel sichtbar, aber ich denke, die EDT hat keinen Zugriff darauf. Dies, weil auf eine schnelle Überprüfung fand ich heraus, dass das rawIntensityMapHeatMap Objekt ist nicht null im process() Methode des SwingWorker, aber es ist immer noch null im mouseMoved() Methode, durch die ich einen NullPointerException bekommen.

Das HeatMap Objekt in der GUIMain Klasse und die SwingWorker Klasse erklärt wird, wie:

private HeatMap rawIntensityMap = null; 

Ich habe nicht das rawIntensityMap Objekt an den SwingWorker Klassenkonstruktors senden. Ich hatte das früher versucht, aber es hat nicht funktioniert. Hier

ist die process() Methode aus der SwingWorker Klasse:

@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); 
     } 
    }); 

    } 

Hier ist die mouseMoved() Methode:

@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(); 
     } 
    } 

Hier ist die grundlegende Struktur meiner SwingWorker Klasse:

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); 
} 


} 

} 

Kann jemand auf den er verweisen ror hier?

einige weitere Code:

Das ist mein GUIMain Klasse, wo HeatMap rawIntensityMap deklariert wird. Außerdem habe ich Teile des Codes eingefügt, wo dieses HeatMap Objekt tatsächlich verwendet wird (nicht alle Methoden eingefügt).

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(); 
      } 
     } 

    } 

Der Code aus der SwingWorker Klasse ist bereits oben eingefügt.

+2

Vollständige Beispiele sind [hier] (http://stackoverflow.com/a/25043676/230513) und [hier] (http://stackoverflow.com/a/16880714/230513) zu sehen. – trashgod

Antwort

2

Sie haben zwei vollständig separate Felder mit dem Namen rawIntensityMap.

Sie haben GUIMain.rawIntensityMap und FileReadWorker.rawIntensityMap. Sie weisen FileReadWorker.rawIntensityMap in FileReadWorker::doInBackground zu, aber Sie weisen niemals einem beliebigen Wert zu.

Versuchen Sie, einen Setter für rawIntensityMap in GUIMain Erstellen und guiClassObject.setRawIntensityMap(rawIntensityMap); in FileReadWorker::done aufrufen.

+0

Ich versuchte mit 'volatile', aber es löst das Problem nicht. Ich habe diese Deklaration - "volatile HeatMap rawIntensityMap;" sowohl in der 'GUIMain'-Klasse als auch in der' SwingWorker'-Klasse gemacht. Sollte ich für den komplizierten Fix 'Heatmap heatmap' in der' GUIMain' Klasse deklarieren und Änderungen in der 'mouseMoved' Methode vornehmen? Ich habe nicht ganz verstanden, welche Änderungen vorgenommen werden müssen. Ich möchte diesen Fix zuerst versuchen und wenn es das Problem nicht löst, dann werde ich ein minimales Beispiel geben (da ich mir Zeit nehmen werde, eins zu schreiben. Habe es früher nicht getan). – novicegeek

+0

@novicegeek Ich bin verwirrt. Sie haben zwei verschiedene Felder namens 'rawIntensityMap'? – Jeffrey

+0

Nein. Ich habe eine Klasse 'GUIMain', in der' HeatMap rawIntensityMap' deklariert ist. Zuvor hatte ich versucht, dieses 'HeatMap'-Objekt an den' Konstruktor' meiner 'SwingWorker'-Klasse zu übergeben. Ich habe auch ein 'HeatMap'-Objekt mit dem gleichen Namen in dem 'SwingWorker'. In beiden Fällen erhalte ich eine 'NullPointerException', wenn ich nach Beendigung des Hintergrundthreads wieder auf 'rawIntensityMap' zugreifen will. Ist das der falsche Weg? – novicegeek