3

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

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

尽管使用这个 openmap 应用程序进行了解释,但该问题非常普遍,并且据说与 Swing 相关。现在,我只是等待一个固定的时间(一秒钟),但这并不能消除创建不完整地图的风险......

编辑

更多细节 - 我必须从构造一个 (OpenMap) MapPanel 开始,它在内部创建一个 MapBean(JComponent 子类)和一个 MapHandler。然后我为 MapHandler 提供地理层,框架开始在 JComponent 类型 MapBean 上绘制地理数据。

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

4

3 回答 3

4

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

于 2009-08-27T18:38:58.420 回答
1

听起来您需要将更新 JComponent 的底层数据与 Swing 的绘制周期同步。您可以继承您的 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);
            }
        }
    }
}
于 2009-08-27T18:38:53.333 回答
1

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

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

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

 writeToFile(bi);
于 2009-08-27T19:17:41.383 回答