java - agregar - ¿Cómo cambio JPanel dentro de un JFrame sobre la marcha?
agregar jpanel en un jframe en java y netbeans (14)
¡Estaba teniendo exactamente el mismo problema! ¡Increíble! La solución que encontré fue:
- Agregar todos los componentes (JPanels) al contenedor;
- Usando el método setVisible (falso) para todos ellos;
- En la acción del usuario, estableciendo setVisible (verdadero) en el panel que quería mostrar.
// 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 revalidar (), no validar (), no se necesita CardLayout.
Para decirlo de manera simple, hay una aplicación Java simple que consta de JFrame con algunos componentes. Uno de los componentes es un JPanel que debe reemplazarse por otro JPanel en la acción del usuario.
Entonces, ¿cuál es la forma correcta de hacer tal cosa? He intentado
panel = new CustomJPanelWithComponentsOnIt();
parentFrameJPanelBelongsTo.pack();
pero esto no funcionará ¿Qué sugieres?
1) Configurando el primer Panel:
JFrame frame=new JFrame();
frame.getContentPane().add(new JPanel());
2) Reemplazar el panel:
frame.getContentPane().removeAll();
frame.getContentPane().add(new JPanel());
También tenga en cuenta que debe hacer esto en el subproceso del evento, para asegurar que use SwingUtilities.invokeLater o SwingWorker
En la acción del usuario:
// tienes que hacer algo a lo largo de las líneas de
myJFrame.getContentPane().removeAll()
myJFrame.getContentPane().invalidate()
myJFrame.getContentPane().add(newContentPanel)
myJFrame.getContentPane().revalidate()
Luego puede cambiar el tamaño de su wndow según sea necesario.
Espero que esta pieza de código te dé una idea de cómo cambiar jPanels dentro de un 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);
}
}
La respuesta layout.replace () solo existe / funciona en GroupLayout Manager.
Otros administradores de diseño (CardLayout, BoxLayout, etc.) NO son compatibles con esta característica, pero requieren que primero RemoveLayoutComponent (y luego AddLayoutComponent (de nuevo. :-) [Simplemente estableciendo el registro en línea recta]
Le sugiero que agregue ambos paneles en la creación del cuadro, luego cambie el panel visible llamando a setVisible (verdadero / falso) en ambos. Al llamar a setVisible, se notificará al padre y se le pedirá que vuelva a pintar.
Los otros individuos respondieron la pregunta. Quiero sugerirle que use un JTabbedPane en lugar de reemplazar el contenido. Como regla general, es malo que los elementos visuales de su aplicación desaparezcan o sean reemplazados por otro contenido. Ciertamente, hay excepciones para cada regla, y solo usted y su comunidad de usuarios pueden decidir el mejor enfoque.
Simplemente llame al paquete de métodos () después de configurar el ContentPane
, ( java 1.7
, quizás más antiguo) de la siguiente manera:
JFrame frame = new JFrame();
JPanel panel1 = new JPanel();
JPanel panel2 = new JPanel();
....
frame.setContentPane(panel1);
frame.pack();
...
frame.setContentPane(panel2);
frame.pack();
...
Su caso de uso, parece perfecto para CardLayout .
En el diseño de la tarjeta, puede agregar varios paneles en el mismo lugar, pero luego mostrar u ocultar, un panel a la vez.
Todo depende de cómo va a ser utilizado. Si desea cambiar entre estos dos paneles, utilice CardLayout. Si solo está cambiando de la primera a la segunda vez (y no regresando), entonces la sugerencia de y simplemente la reemplazaría. Aunque si el JPanel no es lo único en su marco, usaría remove(java.awt.Component) lugar de removeAll.
Si se encuentra en algún punto intermedio entre estos dos casos, básicamente se trata de una compensación de tiempo-espacio. CardLayout le ahorrará tiempo pero ocupará más memoria al tener que mantener todo este otro panel en la memoria en todo momento. Pero si solo reemplaza el panel cuando es necesario y lo construye según demanda, no tiene que mantener ese meory pero le lleva más tiempo cambiarlo.
También puedes probar un JTabbedPane para usar pestañas en su lugar (es incluso más fácil que CardLayout porque maneja el mostrar / ocultar automáticamente)
puede usar el método de reemplazo de un diseño:
layout.replace(existingComponent, newComponent)
los componentes existentes y nuevos también pueden ser JPanels.
Problema : mi componente no aparece después de que lo agregué al contenedor.
Debe invocar revalidate y revalidate repaint después de agregar un componente antes de que aparezca en su contenedor.
Fuente: http://docs.oracle.com/javase/tutorial/uiswing/layout/problems.html
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
}
A veces puedes hacer el trabajo sin utilizar la revalidación y, a veces, sin utilizar el repintado. Mi consejo es usar ambos.
frame.setContentPane(newContents());
frame.revalidate(); // frame.pack() if you want to resize.
Recuerde, el uso de Java ''copiar referencia por valor'' pasa el argumento. Entonces, cambiar una variable no cambiará las copias de la referencia pasada a otros métodos.
También tenga en cuenta que JFrame
es muy confuso en el nombre de usabilidad. Agregar un componente o establecer un diseño (normalmente) realiza la operación en el panel de contenido. Por extraño que parezca, obtener el diseño realmente te da el administrador de diseño del marco.