Pergunta

Eu estou trabalhando em Java, e eu tenho um JPanel em um JFrame. Nesse JPanel, entre outras coisas, eu tenho um JLabel que eu quero fazer aparecer e desaparecer à vontade. Eu tentei configurar a visibilidade para true / false, adicionando e removendo-o do JFrame e JPanel, e, tendo parecia on-line, eu tentei validate () ing e revalidate () ing ad infinitum. O que pode ser feito aqui para resolver este problema?

Foi útil?

Solução

Em geral, chamando o método setVisible é suficiente para fazer um componente Swing para ser mostrado ou oculto.

Só para ter certeza de que ele funciona, eu tentei o seguinte:

public class Visibility {
  private void makeGUI() {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    final JLabel l = new JLabel("Hello");
    final JButton b = new JButton("Hide Label");
    b.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        l.setVisible(false);
      }
    });

    f.getContentPane().setLayout(new BorderLayout());
    f.getContentPane().add(l, BorderLayout.CENTER);
    f.getContentPane().add(b, BorderLayout.SOUTH);
    f.setSize(200, 200);
    f.setLocation(200, 200);
    f.validate();
    f.setVisible(true);
  }

  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        new Visibility().makeGUI();
      }
    }); 
  }
}

O programa acima é capaz de afetar a visibilidade ao clicar em um JButton.

Poderia ser um problema de segmentação?

Meu próximo suspeita era de que talvez um Thread que não está no segmento de eventos expedição (EDT) não pode estar afetando a exibição imediatamente, então eu adicionei o seguinte depois de inicializar o JLabel e JButton.

Thread t = new Thread(new Runnable() {
  public void run() {
    while (true) {
      b.setVisible(!b.isVisible());

      try {
        Thread.sleep(100);
      } catch (InterruptedException e) { /* Handle exception /* }
    }
  }
});

t.start();

Com o novo Thread execução, ele mudou o alternado a visibilidade do JLabel cada 100 ms, e isso também funcionou sem problema.

Chamar um componente Swing fora do segmento de eventos expedição (EDT ) é uma coisa ruim, como balanço não é thread-safe. Eu estava um pouco surpreso que funcionou, e o fato de que ele funciona pode ser apenas um acaso .

repintar o JPanel?

Se a visibilidade do JLabel única está sendo afetado em redimensionamento, isso provavelmente significa que o JLabel está sendo desenhado somente quando o JPanel está sendo redesenhada.

Uma coisa é tentar chamar do JPanel repaint método para ver se a visibilidade do JLabel vai mudar.

Mas este método parece ser apenas um band-aid para uma situação, se a principal causa é devido a um fio fora do EDT está tentando fazer alterações no GUI. (Assim como uma nota, o método repaint é thread-safe, para que ele possa ser chamado por tópicos off-EDT, mas contando com repaint é uma solução do que uma solução.)

Tente usar SwingUtilities.invokeLater

Finalmente, provavelmente a coisa que eu tentaria é o SwingUtilities.invokeLater método, que pode ser chamado (e só deve ser chamado) a partir de um fio condutor separado do EDT, se quiser afetar a GUI.

Assim, o exemplo Thread anteriormente deve ser escrita como:

Thread t = new Thread(new Runnable() {
  public void run() {
    while (true) {
      try {
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            b.setVisible(!b.isVisible());
          }
        });
      } catch (Exception e1) { /* Handle exception */ }

      try  {
        Thread.sleep(100);
      } catch (InterruptedException e) { /* Handle exception */ }
    }
  }
});

t.start();

Se a mudança para o GUI realmente está acontecendo em um segmento separado, então eu recomendo a leitura Lição: simultaneidade no swing de O Java Tutoriais , a fim de saber mais informações sobre como escrever bem comportando código de multi-threaded usando swing.

Outras dicas

setVisible () ou removê-lo deve funcionar bem, certifique-se que você está fazendo isso a partir do segmento de eventos expedição embora. Existem métodos de utilidade pública em EventQueue para a execução de blocos em que fio.

http: / /helpdesk.objects.com.au/java/how-do-i-update-my-gui-from-any-thread

Você precisa chamar revalidate () nos JPanel pais se você precisar de seus componentes para ser re-definidos.

Se você pode postar um exemplo que demonstra o problema que eu possa ter um olhar para isso por você.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top