我需要一种等待(Swing)JComponent完全绘制的方法。这个实际问题来自openmap应用程序:任务是绘制一个带有几个图层的地图(mapBean)并从该地图创建一个图像。
不幸的是,并且清楚地记录了,图像格式化程序从地图中获取当前状态以创建图片,并且有机会,特别是当地图变得复杂时,格式化程序在mapBean(JComponent)被绘制之前被调用
虽然用这个openmap应用程序解释,但问题很普遍,据说与Swing有关。现在,我只是等待一段固定时间(一秒钟),但这并不能消除创建不完整地图的风险......
修改
更多细节 - 我必须从构建一个(OpenMap)MapPanel开始,其中internallz创建一个MapBean(JComponent子类)和一个MapHandler。然后我使用地理层为MapHandler提供源代码,框架开始在JComponent类型MapBean上绘制地理数据。
将所有图层添加到Map后,我使用另一个框架类来创建JPG图像(或者:保存图像数据的byte [])。如果我不等待,这个可能会导致问题:这个'图像创建者'从地图bean的当前状态创建图像,如果我把这个'图像创建者'称为早期,一些地图图层不会被绘制和丢失。很烦人......
答案 0 :(得分:3)
java.awt.EventQueue.invokeLater
将允许您在绘制操作完成后运行任务。如果它正在进行某种异步加载,那么它将是特定于API的(MediaTracker
为Image
执行。)
答案 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);