2008-10-20 409 views
38

Para ponerlo simple, hay una aplicación java swing 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.¿Cómo cambio JPanel dentro de un JFrame sobre la marcha?

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

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

pero esto no funcionará. ¿Qué sugieres?

Respuesta

47

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.

+3

Al usar CardLayout, tenga en cuenta que el tamaño preferido para el panel que lo use será el tamaño del panel MÁS GRANDE en el diseño. Si desea que se reclame el espacio, querrá usar setVisible (false) y setPreferredSize (new Dimension (0,0)) para ocultar un componente. –

+0

No había oído hablar de CardLayout antes. Gracias - fue perfecto para algo que necesitaba hacer. – I82Much

+0

Sí. Esta es la forma correcta. Quizás el mejor. – FaithReaper

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

Recuerde, el uso de Java 'copia de 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 JFrame es muy confuso en el nombre de la 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.

+0

Tom, gracias por su Respuesta: No pretendo reemplazar el panel de contenido, solo un jpanel colocado sobre él (como frame.add (jpanel1), frame.add (jpanel2), frame.agregar (jpanel3)). ¿Podría sugerir una solución sensata en el código? – yanchenko

+0

Hola John, Tu caso de uso, parece perfecto para CardLayout. http://java.sun.com/docs/books/tutorial/uiswing/layout/card.html En el diseño de la tarjeta, puede agregar varios paneles en el mismo lugar, pero luego mostrar u ocultar, un panel en un hora. –

+0

@swapnonil: Haz una respuesta para poder votar. :) –

0

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.

22

1) Ajuste el primer panel:

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

2) Sustitución del panel:

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

Nótese también que hay que hacer esto en el hilo de eventos, para garantizar este uso el SwingUtilities.invokeLater o el SwingWorker

1

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.

3

Todo depende de cómo va a ser utilizado. Si desea alternar entre estos dos paneles, utilice CardLayout. Si solo está cambiando del primero al segundo una vez (y no regresando), entonces usaría la sugerencia de telcontar y simplemente la reemplazará. Aunque si el JPanel no es lo único en su marco, usaría remove(java.awt.Component) en lugar de removeAll.

Si se encuentra en algún punto intermedio entre estos dos casos, es básicamente 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 puede probar con una JTabbedPane usar pestañas en su lugar (es incluso más fácil que CardLayout ya que maneja el mostrar/ocultar automitically)

5

En la acción del usuario:

// que tiene que hacer algo a lo largo las líneas de

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

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

entonces se puede cambiar el tamaño de wndow según sea necesario.

6

Espero que este fragmento 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); 
     } 
} 
1

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

  1. Agregando todos los componentes (JPanels) al contenedor;
  2. Usando el método setVisible (falso) para todos ellos;
  3. 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); 

Sin revalidate(), sin validar(), sin CardLayout necesario.

0
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 se puede hacer el trabajo sin necesidad de utilizar la revalidación y, a veces sin necesidad de utilizar el uso asesoramiento repaint.My ambos.

0

Sólo tiene que llamar al método pack() después de ajustar el ContentPane, (java 1.7, tal vez más) 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(); 
... 
-1

puede utilizar la sustitución método de diseño :

layout.replace(existingComponent, newComponent) 

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

1

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

Otros LayoutManagers (CardLayout, BoxLayout etc) no soportan esta característica, pero requieren que primero RemoveLayoutComponent (y luego AddLayoutComponent (de nuevo. :-) [Sólo estableciendo el récord recta]

Cuestiones relacionadas