如何等待JComponent完全绘制?

时间:2009-08-27 18:29:15

标签: java swing openmap

我需要一种等待(Swing)JComponent完全绘制的方法。这个实际问题来自openmap应用程序:任务是绘制一个带有几个图层的地图(mapBean)并从该地图创建一个图像。

不幸的是,并且清楚地记录了,图像格式化程序从地图中获取当前状态以创建图片,并且有机会,特别是当地图变得复杂时,格式化程序在mapBean(JComponent)被绘制之前被调用

虽然用这个openmap应用程序解释,但问题很普遍,据说与Swing有关。现在,我只是等待一段固定时间(一秒钟),但这并不能消除创建不完整地图的风险......

修改

更多细节 - 我必须从构建一个(OpenMap)MapPanel开始,其中internallz创建一个MapBean(JComponent子类)和一个MapHandler。然后我使用地理层为MapHandler提供源代码,框架开始在JComponent类型MapBean上绘制地理数据。

将所有图层添加到Map后,我使用另一个框架类来创建JPG图像(或者:保存图像数据的byte [])。如果我不等待,这个可能会导致问题:这个'图像创建者'从地图bean的当前状态创建图像,如果我把这个'图像创建者'称为早期,一些地图图层不会被绘制和丢失。很烦人......

3 个答案:

答案 0 :(得分:3)

java.awt.EventQueue.invokeLater将允许您在绘制操作完成后运行任务。如果它正在进行某种异步加载,那么它将是特定于API的(MediaTrackerImage执行。)

答案 1 :(得分:1)

听起来您需要使用Swing的绘制周期同步更新JComponent的基础数据。您可以对JComponent进行子类化并装饰paintComponent()方法,您也可以查看ImageObserver.imageUpdate(),但我不确定这是否会告诉您需要什么。

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

答案 2 :(得分:1)

您也可以尝试使用屏幕外缓冲区渲染图像:

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

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

 writeToFile(bi);