Domanda

Per dirla in modo semplice, c'è una semplice app java swing che consiste in JFrame con alcuni componenti al suo interno. Uno dei componenti è un JPanel che deve essere sostituito da un altro JPanel sull'azione dell'utente.

Allora, qual è il modo corretto di fare una cosa del genere? Ho provato

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

ma questo non funzionerà. Cosa suggeriresti?

È stato utile?

Soluzione

Il tuo caso d'uso sembra perfetto per CardLayout .

Nel layout delle carte puoi aggiungere più pannelli nello stesso posto, ma poi mostrare o nascondere un pannello alla volta.

Altri suggerimenti

1) Impostazione del primo pannello:

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

2) Sostituzione del pannello:

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

Nota anche che devi farlo nel thread dell'evento, per assicurarti di usare SwingUtilities.invokeLater o SwingWorker

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

Ricorda, Java usa il passaggio dell'argomento 'copia riferimento per valore'. Pertanto, la modifica di una variabile non modifica le copie del riferimento passate ad altri metodi.

Nota anche che JFrame è molto confuso nel nome dell'usabilità. L'aggiunta di un componente o l'impostazione di un layout (in genere) esegue l'operazione nel riquadro del contenuto. Stranamente, ottenere il layout ti dà davvero il layout manager del frame.

Spero che questo codice ti dia l'idea di cambiare jPanels all'interno di 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);
        }
}

Sull'azione dell'utente:

// devi fare qualcosa in linea con

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

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

Quindi puoi ridimensionare il tuo wndow secondo necessità.

Tutto dipende da come verrà utilizzato. Se si desidera alternare tra questi due pannelli, utilizzare un CardLayout. Se passi dal primo al secondo solo una volta (e non torni indietro), utilizzerei il suggerimento di telcontar e basta sostituirlo. Tuttavia, se JPanel non fosse l'unica cosa nel tuo frame, lo userei rimuovi (java .awt.Component) invece di removeAll.

Se ci si trova tra questi due casi, è fondamentalmente un compromesso spazio-temporale. CardLayout ti farà risparmiare tempo ma occuperà più memoria dovendo tenere sempre in memoria l'intero altro pannello. Ma se si sostituisce il pannello quando necessario e lo si costruisce su richiesta, non è necessario mantenere quella memoria ma ci vuole più tempo per passare.

Inoltre puoi provare un JTabbedPane a usare invece le schede (è ancora più facile di CardLayout perché gestisce automaticamente la visualizzazione / nascondersi)

Le altre persone hanno risposto alla domanda. Voglio suggerire di utilizzare un JTabbedPane invece di sostituire il contenuto. Come regola generale, è male che gli elementi visivi dell'applicazione scompaiano o vengano sostituiti da altri contenuti. Certamente ci sono eccezioni ad ogni regola e solo tu e la tua comunità di utenti potete decidere l'approccio migliore.

Problema : il mio componente non viene visualizzato dopo averlo aggiunto al contenitore.

Devi invocare revalidate e ridipingere dopo aver aggiunto un componente prima che venga visualizzato nel tuo contenitore.

Fonte: http://docs.oracle.com/javase/ tutorial / uiswing / layout / problems.html

Avevo esattamente lo stesso problema !! Chetumal !! La soluzione che ho trovato è stata:

  1. Aggiunta di tutti i componenti (JPanels) al contenitore;
  2. Utilizzando il metodo setVisible (false) per tutti;
  3. All'azione dell'utente, impostare setVisible (true) sul pannello che volevo spettacolo.
// 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 (), no validate (), non è necessario CardLayout.

La risposta layout.replace () esiste / funziona solo su GroupLayout Manager.

Altri LayoutManager (CardLayout, BoxLayout ecc.) NON supportano questa funzione, ma richiedono prima di rimuovere RemoveLayoutComponent (e quindi AddLayoutComponent (indietro di nuovo. :-) [Basta impostare il record direttamente]

Ti suggerisco di aggiungere entrambi i pannelli alla creazione del frame, quindi cambiare il pannello visibile chiamando setVisible (true / false) su entrambi. Quando si chiama setVisible, il genitore verrà avvisato e verrà chiesto di ridipingere se stesso.

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 volte puoi fare il lavoro senza usare la riconvalida ea volte senza usare la riverniciatura. Il mio consiglio è di usare entrambi.

Basta chiamare il metodo pack () dopo aver impostato ContentPane , ( java 1.7 , forse precedente) in questo modo:

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

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

puoi usare il metodo di sostituzione di un layout:

layout.replace(existingComponent, newComponent)

anche i componenti esistenti e nuovi possono essere JPanels.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top