How do I wait for the JComponent to be fully colored?

I need to wait for the JComponent to fully Swing. This actual problem arises from the openmap application: the task is to draw a map (mapBean) with multiple layers and create an image from this map.

Unfortunately, and this is clearly documented, the image formatter takes the current state from the map to create the picture, and there is a chance, especially when maps get complex, that the formatting is called before the mapBean, the JComponent, is drawn.

While this is explained using the openmap app, the problem is fairly general and presumably Swing. Right now, I'm just waiting for a certain amount of time (one second), but that doesn't eliminate the risk of creating incomplete maps ...

Edit

Some details - I have to start by creating a MapPanel (OpenMap) which internallz subclasses MapBean (JComponent) and MapHandler. Then I feed the MapHandler with geographic layers and the Framework starts drawing geographic data 'on' of type JComponent MapBean.

After adding all the layers to the Map, I use another framework class to create the JPG image (or: byte [] which contains the image data). And it can cause problems if I don't wait: this image creator creates an image from the current state of the map bean, and if I call it "image creator" early on, some of the map layers will not be colored and missing. Pretty annoying ...

+2


source to share


3 answers


java.awt.EventQueue.invokeLater

will allow you to start the task after the drawing operation is complete. If it does some kind of asynchronous load, then it will be API specific (as MediaTracker

for Image

).



+3


source


It looks like you need to synchronize the update of the underlying JComponent with your Swing draw loop. You can subclass the JComponent and decorate the method paintComponent()

, you can also take a look ImageObserver.imageUpdate()

, although I'm not sure if this tells you what you want.



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

      

+1


source


You can also try using an off-screen buffer to render your image:

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

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

 writeToFile(bi);

      

+1


source







All Articles