Как дождаться, пока JComponent будет полностью раскрашен?
Вопрос
Мне нужен способ дождаться, пока JComponent (Swing) не будет полностью нарисован.Эта актуальная проблема возникает из-за приложения openmap:Задача состоит в том, чтобы нарисовать карту (mapBean) с парой слоев и создать изображение на основе этой карты.
К сожалению, и это четко задокументировано, программа форматирования изображений использует текущее состояние карты для создания изображения, и есть вероятность, особенно когда карты становятся сложными, что программа форматирования вызывается до того, как будет нарисован mapBean, JComponent.
Хотя проблема объясняется с помощью этого приложения openmap, она довольно общая и предположительно связана с Swing.Прямо сейчас я просто жду определенное время (одну секунду), но это не устраняет риск создания неполных карт...
Редактировать
Еще несколько деталей - я должен начать с построения (OpenMap) MapPanel, которая внутренне создает MapBean (подкласс JComponent) и MapHandler.Затем я загружаю в MapHandler географические слои, и Фреймворк начинает отображать географические данные "на" типе JComponent MapBean.
После добавления всех слоев на карту я использую другой класс framework для создания изображения в формате JPG (или:байт[], который содержит данные изображения).И это может возникнуть проблема, если я не подожду:этот "создатель изображений" создает изображение из текущего состояния компонента map, и если я вызову этот "создатель изображений" пораньше, некоторые слои карты не будут закрашены и пропадут.Довольно раздражает...
Решение
java.awt.EventQueue.invokeLater
позволит вам запустить задачу после завершения операции рисования.Если он выполняет какую-то асинхронную загрузку, то он будет специфичен для API (как MediaTracker
делает для Image
).
Другие советы
Вы также можете попробовать использовать внеэкранный буфер для рендеринга вашего изображения в:
MapBean map = new MapBean();
map.setData(...);
BufferedImage bi = new BufferedImage(...);
map.paintComponent(bi.getGraphics());
writeToFile(bi);
Похоже, вам нужно синхронизировать обновление базовых данных вашего 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);
}
}
}
}