Pergunta

Preciso de uma maneira de esperar até que um JComponent (balanço) esteja totalmente pintado. Esse problema real surge de um aplicativo OpenMap: a tarefa é desenhar um mapa (MapBean) com algumas camadas e criar uma imagem desse mapa.

Infelizmente, e está claramente documentado, o formatador da imagem pega o estado atual do mapa para criar a imagem, e há uma chance, especialmente quando os mapas se tornam complexos, que o formatador é chamado antes do MapBean, um JComponent, é pintado.

Embora explicado com esse aplicativo OpenMap, o problema é bastante geral e supostamente relacionado a swing. No momento, apenas espero um tempo fixo (um segundo), mas isso não elimina o risco de criar mapas incompletos ...

Editar

Mais alguns detalhes - tenho que começar com a construção de um MappAnel (OpenMap), que o Internallz cria uma MapBean (subclasse JComponent) e um Maphandler. Em seguida, alimento o Maphandler com camadas geográficas e a estrutura começa a pintar os dados geográficos 'sobre' o tipo jcomponent MapBean.

Depois de adicionar todas as camadas ao mapa, uso outra classe de estrutura para criar uma imagem JPG (ou: o byte [] que contém os dados da imagem). E isto pode causar problemas, se eu não esperar: este 'criador de imagens' cria a imagem do estado atual do mapa e se eu chamar isso de 'criador de imagem' para cedo, algumas camadas de mapa não serão pintadas e ausentes. Muito irritante ...

Foi útil?

Solução

java.awt.EventQueue.invokeLater Permitirá que você execute uma tarefa após o término da operação de tinta. Se estiver fazendo algum tipo de carga assíncrona, será específico da API (como MediaTracker faz para Image).

Outras dicas

Você também pode tentar usar um buffer fora da tela para renderizar sua imagem em:

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

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

 writeToFile(bi);

Parece que você precisa sincronizar a atualização dos dados subjacentes do seu JComponent com o ciclo de pintura do swing. Você pode subclasse seu JComponent e decorar o paintComponent() método, você também pode olhar para ImageObserver.imageUpdate(), embora não tenha certeza se isso vai lhe dizer o que você deseja.

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);
            }
        }
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top