Question

Je besoin d'un moyen d'attendre jusqu'à ce qu'un (Swing) JComponent est entièrement peint. Ce problème réel provient d'une application OpenMap. La tâche consiste à dessiner une carte (mapBean) avec un couple de couches et de créer une image à partir de cette carte

Unfortunatly, et il est clairement documenté, le formateur d'image prend l'état actuel de la carte pour créer l'image, et il y a une chance, surtout quand les cartes deviennent complexes, que le ist formatter appelé avant la mapBean, un JComponent, est peint .

Bien expliqué avec cette application OpenMap, le problème est tout à fait générale et soi-disant Balancez connexes. En ce moment, je viens attendre un temps fixe (une seconde), mais cela ne supprime pas le risque de créer des cartes incomplètes ...

Modifier

Quelques détails - je dois commencer par la construction d'un (OpenMap) MapPanel, ce qui crée une internallz MapBean (sous-classe JComponent) et un MapHandler. Ensuite, je nourris l'MapHandler avec des couches géographiques et le cadre commence à peindre les données géographiques »sur la MapBean de type JComponent.

Après avoir ajouté toutes les couches à la carte, j'utilise une autre classe de cadre pour créer une image JPG (ou: l'octet [] qui contient les données d'image). Et ce peut causer des problèmes, si je n'attends pas: ce « créateur d'image » crée l'image de l'état actuel de la fève de la carte, et si je l'appelle ce « créateur d'image » au début, certains couches cartographiques ne sont pas peintes et disparus. Assez ennuyeux ...

Était-ce utile?

La solution

java.awt.EventQueue.invokeLater vous permettra d'exécuter une tâche après l'opération de peinture est terminée. Si elle est en train de faire une sorte de charge asynchrone, alors il sera spécifique API (comme le fait pour MediaTracker Image).

Autres conseils

Vous pouvez également essayer d'utiliser un tampon hors écran pour rendre votre image:

 MapBean map = new MapBean();
 map.setData(...);

 BufferedImage bi = new BufferedImage(...);
 map.paintComponent(bi.getGraphics());

 writeToFile(bi);

On dirait que vous devez synchroniser la mise à jour des données sous-jacentes de votre JComponent avec le cycle de peinture de Swing. Vous pouvez sous-classe votre JComponent et décorer la méthode paintComponent(), vous pouvez aussi regarder ImageObserver.imageUpdate(), bien que je ne suis pas sûr si cela va vous dire ce que vous voulez.

public class DrawingCycleAwareComponent extends MyOtherJComponent {

    private final Object m_synchLock = new Object();

    protected void paintComponent(Graphics g) {
        synchronized (m_synchLock) {
            super.paintComponent(g);
        }
    }

    protected void updateData(Object data) {
        if (SwingUtilities.isEventDispatchThread()) {
            reallySetMyData(data);  // don't deadlock yourself if running in swing
        }
        else {
            synchronized (m_synchLock) {
                reallySetMyData(data);
            }
        }
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top