Java Swing revalidate () vs repaint ()

211

Estou montando um aplicativo Swing, onde geralmente desejo substituir o conteúdo de um JPanel. Para fazer isso, estou ligando removeAll(), adicionando meu novo conteúdo e ligando revalidate().

No entanto, estou descobrindo que o conteúdo antigo ainda é realmente visível (embora obscurecido pelo novo conteúdo). Se eu adicionar uma chamada repaint()além de revalidate(), ela funcionará conforme o esperado.

Tenho certeza de que em outras ocasiões já experimentei que basta ligar revalidate().

Então, basicamente, minha pergunta é: devo chamar as duas funções? Caso contrário, quando devo chamar cada uma delas?

William
fonte
6
Este tutorial da Oracle afirma: "Sempre invoque repintar após revalidar". Nenhuma explicação é fornecida.
mins

Respostas:

154

Você precisa ligar repaint()e revalidate(). O primeiro diz a Swing que uma área da janela está suja (o que é necessário para apagar a imagem das crianças removidas por removeAll()); o último diz ao gerente de layout para recalcular o layout (o que é necessário ao adicionar componentes). Isso deve fazer com que os filhos do painel repintem, mas pode não fazer com que o próprio painel faça isso (consulte isso na lista de acionadores de repintar).

Em uma observação mais geral: em vez de reutilizar o painel original, recomendo criar um novo painel e trocá-los no pai.

kdgregory
fonte
1
Você poderia racionalizar por que construir um novo painel é uma solução melhor do que usar o antigo? :)
Arttu
3
@Arttu - é menos trabalho e, portanto, menos propenso a erros.
Kdgregory 14/05
86

Sempre que você remove () ou removeAll (), deve ligar para

  validate();
  repaint();

depois de concluir a adição () dos novos componentes.

Chamar validate () ou revalidate () é obrigatório quando você remove () - consulte os javadocs relevantes.

Meus próprios testes indicam que repaint () também é necessário. Não sei exatamente o porquê.

Noel Grandin
fonte
59

revalidateé chamado em um contêiner assim que novos componentes são adicionados ou antigos são removidos. esta chamada é uma instrução para solicitar ao gerente de layout que redefinir com base na nova lista de componentes. revalidateacionará uma chamada para repintar o que o componente considera 'regiões sujas'. Obviamente, nem todas as regiões do seu JPanelsão consideradas sujas pelo RepaintManager.

repainté usado para dizer a um componente para repintar a si próprio. Geralmente, é necessário chamar isso para limpar condições como a sua.

akf
fonte
5

revalidate()basta solicitar o layout do contêiner, quando você experimenta simplesmente chamar revalidate()obras, isso pode ser causado pela atualização dos limites dos componentes filhos, aciona repaint()quando seus limites são alterados durante o re-layout. No caso mencionado, apenas o componente removido e nenhum limite de componente é alterado; nesse caso, nenhum repaint()é acionado "acidentalmente" .

Antony Ng
fonte
-4

sim, você precisa chamar repaint (); revalidar(); quando você chama removeAll (), é necessário chamar repintar () e revalidar ()

Som Adhikari
fonte