Como posso mudar o JPanel dentro de um JFrame em tempo real?
-
03-07-2019 - |
Pergunta
Para colocá-lo simples, há um aplicativo Java Swing simples que consiste em JFrame com alguns componentes na mesma. Um dos componentes é um JPanel que se destina a ser substituído por outro JPanel na ação do usuário.
Então, qual é a maneira correta de fazer tal coisa um? Eu tentei
panel = new CustomJPanelWithComponentsOnIt();
parentFrameJPanelBelongsTo.pack();
mas isso não vai funcionar. O que você sugere?
Solução
O seu caso de uso, parece perfeito para CardLayout .
No layout do cartão você pode adicionar vários painéis no mesmo lugar, mas, em seguida, mostrar ou esconder, um painel de cada vez.
Outras dicas
1) Definir o primeiro painel:
JFrame frame=new JFrame();
frame.getContentPane().add(new JPanel());
2) Substituindo o painel:
frame.getContentPane().removeAll();
frame.getContentPane().add(new JPanel());
Além disso, observe que você deve fazer isso no Tópico do evento, para garantir que esta utilização do SwingUtilities.invokeLater ou o SwingWorker
frame.setContentPane(newContents());
frame.revalidate(); // frame.pack() if you want to resize.
Lembre-se, o uso Java 'referência cópia por valor' passagem de argumento. Assim, alterando a variável não mudará cópias da referência passado para outros métodos.
Também nota JFrame
é muito confuso em nome da usabilidade. Adicionando um componente ou definir um layout (geralmente) executa a operação no painel de conteúdo. Curiosamente, ficando o layout realmente dar-lhe gerenciador de layout do quadro.
Hope este pedaço de código lhe dar uma idéia de mudar JPanels dentro de um JFrame.
public class PanelTest extends JFrame {
Container contentPane;
public PanelTest() {
super("Changing JPanel inside a JFrame");
contentPane=getContentPane();
}
public void createChangePanel() {
contentPane.removeAll();
JPanel newPanel=new JPanel();
contentPane.add(newPanel);
System.out.println("new panel created");//for debugging purposes
validate();
setVisible(true);
}
}
Na ação do usuário:
// você tem que fazer algo ao longo das linhas de
myJFrame.getContentPane().removeAll()
myJFrame.getContentPane().invalidate()
myJFrame.getContentPane().add(newContentPanel)
myJFrame.getContentPane().revalidate()
Depois, você pode redimensionar a sua wndow conforme necessário.
Tudo depende de como a sua vai ser usado. Se você vai querer alternar entre estes dois painéis, em seguida, usar um CardLayout. Se você está apenas mudança da primeira para a segunda de uma vez (e não voltar), então eu usaria Telcontar sugestão s e apenas substituí-lo. Embora se o JPanel não é a única coisa em seu quadro que eu usaria (java .awt.Component) vez de removeAll.
Se você está em algum lugar entre esses dois casos é basicamente uma troca no tempo-espaço. O CardLayout vai lhe poupar tempo, mas ocupam mais memória por ter que manter todo este outro painel na memória em todos os momentos. Mas se você apenas substituir o painel quando necessário e construí-lo sob demanda, você não tem que manter isso em torno meory mas é preciso mais tempo para switch.
Além disso, você pode tentar um JTabbedPane de guias de uso em vez (o seu ainda mais fácil do que CardLayout porque ele lida com a exibição / escondendo automitically)
Os outros indivíduos responderam a pergunta. Quero sugerir que você use um JTabbedPane em vez de substituir o conteúdo. Como regra geral, é ruim ter elementos visuais de sua aplicação desaparecer ou ser substituído por outro conteúdo. Certamente existem exceções para cada regra, e só você e sua comunidade de usuários pode decidir a melhor abordagem.
Problema :. Meu componente não aparece depois de eu ter adicionado ao recipiente
Você precisa invocar revalidate e repaint depois de adicionar um componente antes que ele vai aparecer em seu recipiente.
Fonte: http://docs.oracle.com/javase/ tutorial / uiswing / layout / problems.html
Eu estava tendo exatamente o mesmo problema !! Increadible !! A solução que encontrei foi:
- A adição de todos os componentes (JPanels) para o recipiente;
- Usando o método setVisible (false) para todas elas;
- Na ação do usuário, estabelecendo setVisible (true) para o painel que eu queria show.
// Hiding all components (JPanels) added to a container (ex: another JPanel)
for (Component component : this.container.getComponents()) {
component.setVisible(false);
}
// Showing only the selected JPanel, the one user wants to see
panel.setVisible(true);
No revalidate (), não validate (), não CardLayout necessário.
A resposta layout.replace () só existe / trabalha no GroupLayout Manager.
Outros LayoutManagers (CardLayout, BoxLayout etc) não suportam esse recurso, mas exigem que você primeiro RemoveLayoutComponent (e, em seguida, AddLayoutComponent (de volta novamente. :-) [Apenas definir o recorde reta]
Eu sugiro que você adicione ambos painel na criação de quadros, em seguida, mudar o painel visível chamando setVisible (true / false) em ambos. Ao chamar setVisible, o pai será notificado e convidado a redesenhar propriamente dito.
class Frame1 extends javax.swing.JFrame {
remove(previouspanel); //or getContentPane().removeAll();
add(newpanel); //or setContentPane(newpanel);
invalidate(); validate(); // or ((JComponent) getContentPane()).revalidate();
repaint(); //DO NOT FORGET REPAINT
}
Às vezes você pode fazer o trabalho sem usar a revalidação e, por vezes, sem usar o uso repaint.My aconselhar ambos.
Apenas chamar o método pack () depois de definir o ContentPane
, (java 1.7
, talvez mais velhos) como este:
JFrame frame = new JFrame();
JPanel panel1 = new JPanel();
JPanel panel2 = new JPanel();
....
frame.setContentPane(panel1);
frame.pack();
...
frame.setContentPane(panel2);
frame.pack();
...
Você pode usar o método de um layout substituir:
layout.replace(existingComponent, newComponent)
os JPanels existentes e novos componentes podem ser também.