webentwicklung-frage-antwort-db.com.de

Wie ändere ich JPanel in einem JFrame im laufenden Betrieb?

Einfach ausgedrückt gibt es eine einfache Swing-App Java), die aus JFrame mit einigen Komponenten besteht. Eine der Komponenten ist ein JPanel, das bei einer Benutzeraktion durch ein anderes JPanel ersetzt werden soll.

Also, wie macht man so etwas richtig? ich habe es versucht

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

aber das wird nicht funktionieren. Was würdest du vorschlagen?

40
yanchenko

Ihr Anwendungsfall scheint perfekt für CardLayout .

Im Kartenlayout können Sie mehrere Bereiche an derselben Stelle hinzufügen, jedoch jeweils einen Bereich ein- oder ausblenden.

51

1) Einstellen des ersten Panels:

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

2) Ersetzen der Verkleidung:

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

Beachten Sie auch, dass Sie dies im Event-Thread tun müssen, um sicherzustellen, dass Sie SwingUtilities.invokeLater oder SwingWorker verwenden

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

Denken Sie daran, dass Java die Übergabe des Arguments 'Referenz nach Wert kopieren' verwendet. Wenn Sie also eine Variable ändern, werden keine Kopien der Referenz geändert, die an andere Methoden übergeben wurde.

Beachten Sie auch, dass JFrame im Namen der Benutzerfreundlichkeit sehr verwirrend ist. Durch Hinzufügen einer Komponente oder Festlegen eines Layouts wird (normalerweise) der Vorgang im Inhaltsbereich ausgeführt. Seltsamerweise erhalten Sie durch das Abrufen des Layouts tatsächlich den Layout-Manager des Rahmens.

18

Hoffe, dieser Code gibt Ihnen eine Vorstellung davon, wie Sie jPanels in einem JFrame ändern können.

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);
        }
}
6
Manoj Fernando

Auf der Benutzeraktion:

// du musst etwas in der Art von tun

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

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

Dann können Sie die Größe Ihres Fensters nach Bedarf ändern.

5
ShawnD

Es hängt alles davon ab, wie es verwendet wird. Wenn Sie zwischen diesen beiden Bedienfeldern wechseln möchten, verwenden Sie ein CardLayout. Wenn Sie nur einmal von der ersten zur zweiten wechseln und (und nicht zurückkehren), würde ich den Vorschlag von telcontar verwenden und ihn einfach ersetzen. Wenn das JPanel nicht das einzige Element in Ihrem Frame ist, würde ich remove (Java.awt.Component) anstelle von removeAll verwenden.

Wenn Sie sich irgendwo zwischen diesen beiden Fällen befinden, handelt es sich im Grunde genommen um einen Kompromiss zwischen Zeit und Raum. Das CardLayout spart Ihnen Zeit, beansprucht jedoch mehr Speicher, da das gesamte andere Bedienfeld jederzeit gespeichert werden muss. Wenn Sie das Panel jedoch nur bei Bedarf austauschen und es nach Bedarf konstruieren, müssen Sie diese Zeit nicht aufrechterhalten, aber es dauert länger, bis das Panel gewechselt ist.

Sie können auch versuchen, in einem JTabbedPane stattdessen Tabs zu verwenden (dies ist sogar einfacher als bei CardLayout, da es das automatische Ein- und Ausblenden übernimmt).

3
luke

Problem: Meine Komponente wird nicht angezeigt, nachdem ich sie dem Container hinzugefügt habe.

Sie müssen revalidate und repaint nach dem Hinzufügen eine Komponente aufrufen, bevor sie angezeigt wird in Ihrer Container.

Quelle: http://docs.Oracle.com/javase/tutorial/uiswing/layout/problems.html

1
Arthur Ronald

Die Antwort layout.replace () existiert/funktioniert nur im GroupLayout Manager.

Andere LayoutManager (CardLayout, BoxLayout usw.) unterstützen diese Funktion NICHT. Sie müssen jedoch zuerst RemoveLayoutComponent (und dann AddLayoutComponent (wieder zurück. :-) [Einfach den Datensatz gerade einstellen]

1
Warren K

Ich hatte genau das gleiche Problem !! Unleserlich !! Die Lösung, die ich gefunden habe, war:

  1. Hinzufügen aller Komponenten (JPanels) zum Container;
  2. Verwenden Sie für alle die Methode setVisible (false).
  3. Setzen Sie bei einer Benutzeraktion setVisible (true) auf das Bedienfeld, das ich anzeigen wollte.
// 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);

Kein Revalidate (), kein Validate (), kein CardLayout erforderlich.

1
Gabriel

Die anderen Personen beantworteten die Frage. Ich möchte vorschlagen, dass Sie ein JTabbedPane verwenden, anstatt Inhalte zu ersetzen. In der Regel ist es schlecht, wenn visuelle Elemente Ihrer Anwendung verschwinden oder durch andere Inhalte ersetzt werden. Natürlich gibt es Ausnahmen zu jeder Regel, und nur Sie und Ihre Benutzergemeinschaft können über den besten Ansatz entscheiden.

1
James A Wilson
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

}

Manchmal können Sie die Arbeit erledigen, ohne die Neuvalidierung zu verwenden, und manchmal, ohne das Repaint zu verwenden. Ich rate, beide zu verwenden.

Rufen Sie einfach die Methode pack () auf, nachdem Sie ContentPane, (Java 1.7, vielleicht älter) so:

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

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

Ich empfehle Ihnen, beide Fenster bei der Rahmenerstellung hinzuzufügen und dann das sichtbare Fenster zu ändern, indem Sie setVisible (true/false) für beide aufrufen. Beim Aufruf von setVisible wird das übergeordnete Element benachrichtigt und aufgefordert, sich neu zu zeichnen.

0
Riduidel