2017-10-17 9 views
0

J'écris un plugin pour un programme de mauvaise mise en page et j'ai des problèmes avec la méthode repaint().Synchronisation de java jpanel avec repaint() ou: Est-ce qu'un Listener peut être ajouté à repaint de swing?

question courte: Y at-il un moyen de s'informer dès que la repeindre un JPanel a été fait ou de synchroniser le code avec lui?

version détaillée:

Mon programme peut tracer un ensemble de données dans un xy graphique à un JPanel et montrer à l'aide jfree.chart; Dans une autre partie du programme j'ai beaucoup de jeux de données (~ 100) que je veux tracer et enregistrer en tant qu'images. J'ai aussi trouvé une solution, mais je ne l'aime vraiment pas. Le problème peut être réduit à une notification sur l'état de la peinture d'un JPanel.

Dans la partie qui doit enregistrer toutes les images que j'ai cette solution:

PlotSpectrum spectrumWindow = getTheWindow(); //pseudo code... 
// some stuff 
ti = storage.getImage(channel, slice, frame, position); 
spectrumWindow.plotData(false, andor.captureSpectrum(ti.pix), wave, 
       centerWave, fineGrating, exposureTime, 
       slitWidth, substractBackground); 
spectrumWindow.repaint(); // probably not necessary 
sleep(100);    // this annoys me... 
spectrumWindow.savePlot(path, true, config, null); 

spectrumWindow est un JPanel qui est également affiché dans une autre fenêtre et tout fonctionne très bien. MAIS je n'aime vraiment pas dormir (100) là-dedans ... sans cela je demande un repeint mais ce n'est pas fait avant d'essayer d'enregistrer un "snapshot" de (c'est ce que fait savePlot. ..). Je sais, autre thread et ces problèmes de synchronisation sacrément ... Avec le sommeil je suis juste en train de le rendre inutile lent et si j'attends pas assez longtemps les images ne sont pas complètement dessinées (par exemple moitié inférieure manquante)

Yat-il un moyen de s'informer dès que la repeinte a été faite? Je serais probablement aussi bien avec un auditeur, mieux serait une solution avec un moniteur ou sth comparable ou une méthode qui est repeindre maintenant (n'existe pas aussi loin que je sais?) L'interface graphique principale (y compris le JPanel spectrumWindow) et le code précédemment collé s'exécute dans différents threads.

Les parties probablement aussi importantes de mon code suivent ici. Veuillez excuser si certaines parenthèses ne correspondent pas ou si certaines variables ne sont pas déclarées, j'ai enlevé beaucoup de code.

grâce schetefan24

class PlotSpectrum extends ApplicationFrame // that extends JFrame 
{ 
public void plotData(boolean backgroundGiven, int[] spect, double[] wave_, 
        double centerWave, boolean fineGrating_, double exposureTime, 
        double slitWidth, boolean substractBackground) 
{ 
//process data and store internally 
replot(); 
} 

private void replot() 
{ 
XYSeries series = new XYSeries("Spectrum"); 
//add data to series 
XYSeriesCollection collection = new XYSeriesCollection(series); 
//setting up some labels and such stuff... 
JFreeChart chart = ChartFactory.createXYLineChart(
     title, 
     "Wavelength [nm]", 
     yLabel, 
     collection, 
     PlotOrientation.VERTICAL, 
     false, 
     false, 
     false 
    ); 
dataPanel.add(new ChartPanel(chart)); // this is contained in a Frame 
} 

public void savePlot(String path, boolean overWriteAll, HashMap<String,String> config, int[][] addData) 
{ 
File output = new File(path); 
//some more stuff, ask overwrite etc 
if(image) 
{ 
    BufferedImage im = createImage(); 
    String extension = path.substring(path.lastIndexOf(".")+1, path.length()); 
    ImageIO.write(im, extension, output); 
} else { 
//that is an textexport, works fine 
} 
} 

public BufferedImage createImage() 
{ 
    JPanel panel = (JPanel) flipChart.getSelectedComponent(); 
    int w = panel.getWidth(); 
    int h = panel.getHeight(); 
    BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); 
    Graphics2D g = bi.createGraphics(); 
    panel.paint(g); 
    return bi; 
} 
} 

Répondre

1

que je veux tracer et enregistrer sous forme d'images.

  1. ajouter les données à un panneau non visible.
  2. créer un BufferedImage du panneau
  3. créer un ImageIcon en utilisant l'image de dessus
  4. mise à jour d'un JLabel (qui a déjà été ajouté à la trame) en utilisant la méthode setIcon(...)
  5. l'étape ci-dessus devrait générer un PropertyChange événement lorsque l'icône change. Vous pouvez utiliser un ProperChangeListener pour écouter cet événement. Lorsque vous recevez l'événement, vous pouvez répéter les étapes 1 à 4.

Consultez Screen Image. Cela vous aidera à créer une image d'un composant non visible.

Notez que vous n'avez pas vraiment besoin des étapes 4-5. Je viens de les ajouter afin que vous ayez un visuel des parcelles pendant leur traitement.Si vous ne voulez pas le visuel alors peut-être que vous venez d'afficher du texte sur un JLabel indiquant quel plot est en cours de conversion.

+0

à l'étape 1: voulez-vous dire un nouveau JPanel ou puis-je prendre le JFrame déjà existant (la classe PlotSpectrum)? avec quelques petits changements dans mon code, je devrais être capable de créer seulement le panneau avec l'image ... La visualisation ne doit pas être ce qui est différent sur le ImageIcon par rapport à la BufferedImage? – schetefan24

+0

@ schetefan24 L'idée est de créer le panneau en mémoire et de ne pas l'ajouter au cadre car votre problème est que vous ne savez pas quand le panneau sera peint. En créant le panneau en mémoire et en créant votre propre image du panneau, vous contrôlez le processus, pas le mécanisme de peinture de Swing. – camickr

+0

J'ai testé un peu avec les déclencheurs de visibilité et d'événement: le plus simple est de définir l'ensemble de l'image invisible avant de commencer à sauvegarder et d'appeler pack() pour rafraîchir l'image: D semble encore un peu sale mais fonctionne parfaitement :) et merci pour l'indice avec la visibilité; Il semble que je supprime le cadre du contrôle Swings par celui-ci – schetefan24