Как ждать, пока JComponent не будет полностью окрашен? - PullRequest
3 голосов
/ 27 августа 2009

Мне нужен способ подождать, пока (Swing) JComponent не будет полностью окрашен. Эта актуальная проблема возникает из приложения openmap: задача состоит в том, чтобы нарисовать карту (mapBean) с парой слоев и создать изображение из этой карты.

К сожалению, и это четко задокументировано, средство форматирования изображения берет текущее состояние с карты для создания изображения, и есть вероятность, особенно когда карты становятся сложными, что средство форматирования вызывается до того, как mapBean, JComponent, нарисован .

Хотя это и объясняется в этом приложении openmap, проблема довольно общая и предположительно связана с Swing. Прямо сейчас я просто жду фиксированное время (одну секунду), но это не устраняет риск создания неполных карт ...

Редактировать

Еще несколько деталей - я должен начать с создания (OpenMap) MapPanel, который internallz создает MapBean (подкласс JComponent) и MapHandler. Затем я наполняю MapHandler географическими слоями, и Framework начинает рисовать географические данные «на» JComponent типа MapBean.

После добавления всех слоев на карту я использую другой каркасный класс для создания изображения JPG (или: байта [], который содержит данные изображения). И это может вызвать проблемы, если я не буду ждать: этот 'создатель изображения' создает изображение из текущего состояния bean-компонента карты, и если я вызываю этого 'создателя изображения' на раннем этапе, какая-то карта слои не окрашены и отсутствуют. Довольно раздражает ...

Ответы [ 3 ]

4 голосов
/ 27 августа 2009

java.awt.EventQueue.invokeLater позволит вам выполнить задачу после завершения операции рисования. Если он выполняет какую-то асинхронную загрузку, то это будет зависеть от API (как MediaTracker для Image).

1 голос
/ 27 августа 2009

Вы также можете попробовать использовать внеэкранный буфер для рендеринга вашего изображения в:

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

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

 writeToFile(bi);
1 голос
/ 27 августа 2009

Похоже, вам нужно синхронизировать обновление базовых данных вашего 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);
            }
        }
    }
}
...