Pregunta

Para decirlo de manera simple, hay una aplicación java swing simple que consiste en JFrame con algunos componentes. Uno de los componentes es un JPanel que debe ser reemplazado por otro JPanel en la acción del usuario.

Entonces, ¿cuál es la forma correcta de hacer tal cosa? Lo he intentado

panel = new CustomJPanelWithComponentsOnIt();
parentFrameJPanelBelongsTo.pack();

pero esto no funcionará. ¿Qué sugerirías?

¿Fue útil?

Solución

Su caso de uso, parece perfecto para CardLayout .

En el diseño de la tarjeta, puedes agregar varios paneles en el mismo lugar, pero luego mostrar u ocultar, un panel a la vez.

Otros consejos

1) Configuración del primer panel:

JFrame frame=new JFrame();
frame.getContentPane().add(new JPanel());

2) Reemplazo del panel:

frame.getContentPane().removeAll();
frame.getContentPane().add(new JPanel());

También tenga en cuenta que debe hacer esto en el subproceso del evento, para asegurarse de que use el SwingUtilities.invokeLater o SwingWorker

frame.setContentPane(newContents());
frame.revalidate(); // frame.pack() if you want to resize.

Recuerde, Java usa el argumento de 'copiar referencia por valor'. Por lo tanto, 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 configurar 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.

Espero que este fragmento de código te dé una idea de 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);
        }
}

En la acción del usuario:

// tienes que hacer algo en la línea de

myJFrame.getContentPane().removeAll()
myJFrame.getContentPane().invalidate()

myJFrame.getContentPane().add(newContentPanel)
myJFrame.getContentPane().revalidate()

Luego puedes cambiar el tamaño de tu ventana según sea necesario.

Todo depende de cómo se va a utilizar. Si desea alternar entre estos dos paneles, use un CardLayout. Si solo cambia de la primera a la segunda una vez y (y no retrocede), entonces usaría la sugerencia de telcontar y simplemente reemplazarlo. Aunque si el JPanel no es lo único en tu marco, usaría eliminar (java .awt.Component) en lugar de removeAll.

Si estás en algún lugar entre estos dos casos, es básicamente una compensación de espacio-tiempo. El CardLayout le ahorrará tiempo pero ocupará más memoria al tener que mantener este otro panel en la memoria en todo momento. Pero si simplemente reemplaza el panel cuando es necesario y lo construye a pedido, no tiene que mantener esa memoria, pero se necesita más tiempo para cambiar.

También puedes probar un JTabbedPane para usar pestañas (es incluso más fácil que CardLayout porque maneja la visualización / ocultación de forma automática)

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 a cada regla, y solo usted y su comunidad de usuarios pueden decidir el mejor enfoque.

Problema : mi componente no aparece después de haberlo agregado al contenedor.

Debe invocar revalidar y 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

Estaba teniendo exactamente el mismo problema !! ¡Increíble! La solución que encontré fue:

  1. Agregar todos los componentes (JPanels) al contenedor;
  2. Usando el método setVisible (falso) para todos ellos;
  3. En la acción del usuario, configurando 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 revalidate (), validate (), CardLayout necesario.

La respuesta de layout.replace () solo existe / funciona en GroupLayout Manager.

Otros LayoutManagers (CardLayout, BoxLayout, etc.) NO son compatibles con esta función, pero requieren que primero retireLayoutComponent (y luego AddLayoutComponent (de nuevo. :-) [Simplemente configurando el registro directamente]

Le sugiero que agregue ambos paneles en la creación de cuadros, luego cambie el panel visible llamando a setVisible (verdadero / falso) en ambos. Al llamar a setVisible, el padre será notificado y se le pedirá que se vuelva a pintar.

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

}

Algunas veces puedes hacer el trabajo sin usar la revalidación y otras veces sin usar el repintado. Recomiendo usar ambos.

Simplemente llame al método pack () después de configurar ContentPane , ( java 1.7 , quizás más antiguo) de esta manera:

JFrame frame = new JFrame();  
JPanel panel1 = new JPanel(); 
JPanel panel2 = new JPanel(); 
....
frame.setContentPane(panel1);
frame.pack();
...

frame.setContentPane(panel2);
frame.pack();
...

puede utilizar el método de reemplazo de un diseño:

layout.replace(existingComponent, newComponent)

los componentes existentes y nuevos también pueden ser JPanels.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top