JPanels verschachteln

markai

Aktives Mitglied
Hallo!
Meine Freunde und ich arbeiten dzt. an einem kleinen Projekt bei dem jeder seinen eigenen Aufgabenbereich hat. Da die GUI (welche aus einem JFrame mit einem TabbedPane besteht) blöderweise als letztes gebaut wurde, hat nun jeder von uns sie seine App als eigenen JFrame gebaut.
Nun wollen wir das ganze aber zusammenfügen, aber das TappedPane verlangt ja JPanels.

Meine Frage:
Wie kann ich mehrere JPanels als Subpanels in ein JPanel einbauen?

Habe schon versucht die Panels aus der Pallette (arbeite mit NetBeans) hereinzuziehen und dann mit CustomizedCode mein selbst erstelltes Panel zu instanzieren. Das Ergebnis ist aber ein leeres JPanel.

Unser gesamtes Team hat das selbe Problem. Es ist zum verzweifeln ;(
 

hdi

Top Contributor
Du arbeitest also mit einem GUI Builder Tool? Dann war das schon der erste Fehler. Grundsätzlich verstehe ich aber nicht ganz was dein Problem ist. Schachteln von Komponenten:

Java:
JPanel container = new JPanel();
container.setLayout(new GridLayout(2,2));
container.add(panel1);
container.add(panel2);
container.add(panel3);
container.add(panel4);
 

jgh

Top Contributor
in dem du dem JPanel einen entsprechenden LayoutManager setzt.

hiermal ein kl. Bspw. von 3 JPanels die einem mainPanel geaddet werden und dann dem JFrame...

Java:
import java.awt.Color;
import java.awt.GridLayout;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class MainFrame extends JFrame {

	JPanel p1, p2, p3;
	JPanel mainPanel;

	public MainFrame() {
		p1 = new JPanel();
		p1.setBackground(Color.black);
		p2 = new JPanel();
		p2.setBackground(Color.red);
		p3 = new JPanel();
		p3.setBackground(Color.yellow);

		mainPanel = new JPanel();
		mainPanel.setLayout(new GridLayout(3, 1));

		setSize(500, 500);
		setLocationRelativeTo(null);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		mainPanel.add(p1);
		mainPanel.add(p2);
		mainPanel.add(p3);

		add(mainPanel);
		setVisible(true);
	}

	public static void main(String[] args) {
		new MainFrame();
	}
}
 

markai

Aktives Mitglied
@hdi Swing macht das (u.a.) eh genau das, oder?


Java:
private void initComponents() {

        jPanel1 = new FolderHierarchy();
        jPanel2 = new ImagePanel();

        setLayout(new java.awt.BorderLayout());

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 1150, Short.MAX_VALUE)
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 196, Short.MAX_VALUE)
        );

        add(jPanel1, java.awt.BorderLayout.CENTER);

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 1150, Short.MAX_VALUE)
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 107, Short.MAX_VALUE)
        );

        add(jPanel2, java.awt.BorderLayout.PAGE_START);
    }// </editor-fold>                        
    // Variables declaration - do not modify                     
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    // End of variables declaration
 
Zuletzt bearbeitet:

jgh

Top Contributor
Swing macht das (u.a.) eh genau das, oder?

Sorry, den Satz verstehe ich nicht...

Aber da du ja den GUI-Builder von Netbeans zu nutzen scheinst, kann und will ich dir dabei auch nicht helfen...ansonsten habe ich dir eine einfache Möglichkeit gezeigt, wie du bspw. 3 JPanels in einem JPanel anzeigen lassen kannst. Willst du allerdings weiterhin das GroupLayout nutzen, musst du auf andere Hilfe hoffen.
 

hdi

Top Contributor
Nein. Du verwechselst Swing mit deinem GUI Tool. Das GUI Tool generiert dir diesen Code. Normalerweise schreibt man das alles selber. Und GroupLayout ist nur einer LayoutManager die es gibt, und kein besonders schöner.

edit: Wenn du mir nen Screenshot zeigst wie's aussehen soll kann ich dir entsprechenden Code im GridBagLayout schreiben, dann siehst du wie man das normalerweise selber schreibt. GUI tools erzeugen ultraschrottigen Code, und sind gut zum rumspielen um das Design für die GUI zu finden, haben aber imho nichts im Produktiv-Code verloren.
 

markai

Aktives Mitglied
@ jgh: sorry meine antwort war an hdi gerichtet. deine antwort kam schneller als meine. Ich bestehe NICHT auf dieses GUI Tool. Werde mich sogleich an die arbeit machen und deinen Code ausprobieren. Danke für die Hilfe!

@ hdi: Ok, dachte mir man kann das mit dem Tool ganz einfach machen. Aber wenn du meinst dass der code schrott ist wär ich doch eher für eigenen Code.

Wär toll wenn du mir dabei helfen könntest...
(Das JPanel ganz unten ist in einem ScrollPanel, da werden die Bilder hineingeladen wenn sich welche im Ordner befinden)
 

hdi

Top Contributor
Oh, naja ich dachte die GUI ist etwas simpler ;) Ich hoffe du verstehst dass ich jetzt nicht den gesamten Layout-Code schreiben will. Aber grundsätzlich funktioniert das so, dass du auf deinem Container erst den Layout-Manager festlegst (setLayout) und dann Komponenten addest (add/evtl mit Constraints). Einen Überblick über die möglichen Layout-Manager findest du hier:

A Visual Guide to Layout Managers (The Java™ Tutorials > Creating a GUI With JFC/Swing > Laying Out Components Within a Container)

zB deine Buttons im rechten Bereich kannst du schön mit nem GridLayout untereinander ordnen:

Java:
JPanel buttons = new JPanel();
buttons.setLayout(new GridLayout(0,1));
buttons.add(yourButton1);
buttons.add(yourButton2);
// usw...

Das gesamte buttons Panel wiederum kannst du dann einer übergeordneten Komponente adden. zB wenn du diese Buttons jetzt kombinieren willst mit deinem Hauptbereich, wo die Ordner angezeigt werden:

Java:
JPanel overallContent = new JPanel();
overallContent.setLayout(new BorderLayout());
overallContent.add(BorderLayout.CENTER, yourDirectoryPanel);
overallContent.add(BorderLayout.EAST, buttons);

So kann man das halt schachteln. Der Grund-Container ist bei nem Frame das Content Pane, also wenn zu dem overallContent im obigen Code nix mehr dazu kommen würde, dann könntest du gleich das Content Pane dafür benutzen:

Java:
yourJFrame.getContentPane().setLayout(new BorderLayout());
yourJFrame.getContentPane().add(BorderLayout.CENTER, yourDirectoryPanel);
yourJFrame.getContentPane().add(BorderLayout.EAST, buttons);

Wobei das getContentPane() gar nicht nötig ist. Du kannst direkt yourJFrame.add() sagen, denn das leitet intern ans Content Pane weiter.

Es gibt nun auch Layouts wo du nicht einzelne Teilbereiche schachtelst, sondern gleich alles auf einer Ebene zusammenfügst. Dafür bietet sich zB das GridBagLayout an. D.h. du sagst dann direkt:

yourJFrame.getContentPane().setLayout(new GridBagLayout());
yourJFrame.getContentPane().add(<component>, <gridBagConstraints>);

Beim GBL musst du beim adden sog. GridBagConstraints angeben, über die du für die jeweilige Komponente spezifierist wo genau sie liegen soll, wie hoch/breit sie sein soll, inwiefern sie sich beim Resize anpassen soll usw.

Auf jeden Fall solltest du dich mal damit beschäftigen. Deinen GUI Builder solltest du nicht mehr verwenden (nur noch zum Rumspielen mit dem Design, wenn du dir noch überlegen willst wie's am Ende aussehen soll).

Wenn du konkrete Hilfe mit einem Layout brauchst, dann sag Bescheid.
 
Zuletzt bearbeitet:

markai

Aktives Mitglied
Omg! Tausend dank für deine ausführliche Antwort!! (Im echten Leben hättest du dir dafür ein Sixpack verdient :D ) Hatte heute leider keine Zeit mehr, werd mich aber morgen dahinterklemmen und dir dann bescheid geben. Ich vermute mal du hast mir damit eine Menge Zeit und Nerven gespart (Projekt muss am Do fertig sein). Vielen Dank :toll:
 

markai

Aktives Mitglied
Habe heute schon versucht mein Hauptpanel(=Testpanel) mit Hilfe des GridBagLayouts zu layouten. Dazu habe ich zuerst, wie ihr mir geraten habt, auf meinen GUI-Builder verzichtet und das ganze (ButtonPanel, FolderHierarchy und ImagePanel) als Class welche JPanel extended neu erstellt. Bin mir aber nicht sicher welches Layout ich für diese Panels verwenden soll, da dafür ja eigentlich kein Layout notwendig wäre (alle Ordner und Bilder werden über paintComponent() gezeichnet), also habe ich in der initComponent jeweils nur die größe gesetzt.

Java:
setPreferredSize(new java.awt.Dimension(1300, 500));

in meinem Hauptpanel (=Testpanel) welches später in der ferigen GUI dann instanziert werden soll habe ich folgendes gemacht:

Java:
public class TestPanel extends JPanel {

    JPanel folderHierarchyPanel, buttonsPanel, imagePanel;
  
    public TestPanel() {
        folderHierarchyPanel = new FolderHierarchy2();
        imagePanel = new ImagePanel2();
        buttonsPanel = new ButtonsPanel();
        GridBagLayout gbl = new GridBagLayout();
        this.setLayout(gbl);
        GridBagConstraints gbc = new GridBagConstraints();
        
        gbc.fill = GridBagConstraints.HORIZONTAL;
        
        gbc.insets = new Insets(1, 1, 1, 1);
        
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.gridheight = 1;
        gbl.setConstraints(folderHierarchyPanel, gbc);
        add(folderHierarchyPanel);

        gbc.gridx = 1;
        gbc.gridy = 0;
        gbc.gridheight = 2;
        add(buttonsPanel);

        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.gridheight = 1;
        ScrollPane sp = new ScrollPane();
        sp.add(imagePanel);
        gbl.setConstraints(sp, gbc);
        add(sp);

        this.setVisible(true);
    }

In meinem JFrame mache ich folgendes:
Java:
public class App2 extends JFrame {

    JPanel testPanel = new TestPanel();

    public App2() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.getContentPane().add(testPanel);
    }

    public static void main(String[] args) {
        App2 demo = new App2();
        demo.setVisible(true);
    }
}

Herauskommt dabei aber irgendwas. (siehe anhang)

Zum besseren Verständnis, wie das ganze aufgebaut ist habe ich eine Skizze angefügt.

Bitte um Rat! Was mache ich falsch?
 

hdi

Top Contributor
Ich würd das ganze so machen:

ButtonPanel hat GridLayout(0,1). Dort dann einfach deine Buttons per add() von oben nach unten hinzufügen und fertig.

ImagePanel, da kannste wohl ein FlowLayout nehmen. Ich hoffe du malst die einzelnen Bilder nicht direkt per paintComponent da rein. Das ist Quatsch, mach dir ne eigenen Komponenten-Klasse "ImageComponent extends JComponent". Dort malst du in der paintComponent das Bild, aber für jedes Bild hast du n eigenes ImageComponent, und die Dinger addest du ins ImagePanel einfach über add() ins FlowLayout.

Dass in deiner FolderHierarchy die Ordner per paint gezeichnet werden ist der selbe Quatsch. Abgesehen davon dass das ganze dann wohl undynamisch ist macht es das doch auch viel komplizierter zu ermitteln welchen Ordner man angeklickt hat usw. Mach dir auch hier ne eigene Klasse FolderComponent extends JComponent, und dann verpass deine Hierarchy ein passendes Layout.

Dein Content Pane könnte jetzt im einfachsten Fall ein BorderLayout haben. Allerdings scheint es ja dass das Button Panel die gesamte Höhe einnehmen soll. Beim BorderLayout wäre das nicht der Fall, da würde sich die untere Komponente (Image Panel) über die gesamte Breite legen.

GridBagLayout ist da also durchaus ne gute Wahl. Ich hab mir jetzt deinen Code nicht genau angesehen, aber so müsste das funktionieren:

Java:
frame.getContentPane().setLayout(GridBagLayout());
GridBagConstraints c = new GridBagConstraints();

c.gridx = 0;
c.gridy = 0;
c.fill = GridBagConstraints.BOTH;
c.weightx = 1;
c.weighty = 1;
frame.getContentPane().add(folderHierarchy, c);

c.gridx = 1;
c.gridy = 0;
c.fill = GridBagConstraints.VERTICAL;
c.weightx = 0;
c.weighty = 1;
c.gridheight = 2;
frame.getContentPane().add(buttonsPanel, c);

c.gridx = 0;
c.gridy = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1;
c.weighty = 0;
c.gridheight = 1;
frame.getContentPane().add(imagePanel, c);

frame.pack();
 

markai

Aktives Mitglied
Danke erstmal. Wenn du sagst "FolderHierarchy die Ordner per paint gezeichnet werden ist Quatsch" meinst du dann damit dass das keine schöne Lösung ist, oder dass das ganze so nicht funktionieren wird und ich alles neu machen soll (denn ich habs per paintComponent gemacht, und das war eine Menge arbeit :shock:)
 

bERt0r

Top Contributor
Das war sicher eine Menge Arbeit, die du dir ersparen hättest können, weils viel einfacher geht mit einem Layoutmanager. Ob du die Zeit investieren willst zu lernen, wie mans einfacher und eleganter löst bleibt dir überlassen.
Was ich hier im übrigen Anmerken wollte: jeder JFrame speichert seine ganzen Komponenten die er anzeigt in einem Container, das ist das ContentPane. Wenn du dir den von einem Frame mittel getContentPane() holst, kannst du eben diesen Container wieder in einem anderen Frame nach deinen Wünschen einbauen.
z.B
Java:
Frame1 f1=new Frame1();
Frame2 f2=new Frame2();
JFrame f3=new JFrame();

JPanel zweiInEins=new JPanel();
zweiInEins.add(f1.getContentPane());
zweiInEins.add(f2.getContengPane());
f3.setContentPane(zweiInEins);
 

hdi

Top Contributor
Wenn du sagst "FolderHierarchy die Ordner per paint gezeichnet werden ist Quatsch" meinst du dann damit dass das keine schöne Lösung ist, oder dass das ganze so nicht funktionieren wird und ich alles neu machen soll
Kommt drauf an was du noch vorhast.. Man findet immer irgendwie einen Weg. Aber man kann's sich halt schwer machen oder einfach. Der Weg, den du gewählt hast, ist der schwere. D.h. auch im Sinne von nicht schön, nicht elegant. Wenn's jetzt funktioniert, naja dann funktioniert's offenbar. Aber ob dir das in naher Zukunft bei der Implementierung eines neuen Features zum Verhängnis wird, kann man halt nicht sagen. Wie ist das denn zB beim Resize des Frames? Passt sich das Panel dann an, also verändert sich die Größe und/oder Position der Ordner? Das wär auch so ne Sache, die dir ein Layout Manager komplett abnehmen würde. Ich würd's umbauen. Das sollte auch nicht so lange dauern. Es kommt darauf an nach welchem Muster du die Ordner grad zeichnest. Man erkennt ja ne Art Baumstruktur. Die Frage ist ob du die Dinger vllt nicht gleich in nem JTree anzeigen willst - dann musst du nämlich gar nix mehr zeichnen.
 

markai

Aktives Mitglied
Ich will zwar schon lernen wie manns richtig macht, aber da das Projekt - wie gesagt - am Do abgegeben werden muss u ich mit meinen bescheidenen Programmierkenntnissen bereits ca. 40h in diese Ordnerstruktur investiert habe und mehrmals an meine Grenzen gestoßen bin will ich diese JETZT nicht unbedingt umbauen müssen. Bitte habt dafür verständnis und helft mir mit meinem Code. Ich weiß nicht was ich falsch mache... ;(
 

markai

Aktives Mitglied
schon, aber ich würde gerne das main panel zusammenbauen (also alle components FolderHierarchy(), ButtonsPanel()...). und DANN dieses als ganzes im Fram instanzieren.

Wenn ich deinen code richtig verstanden habe baust du dein panel erst im frame zusammen.
Java:
frame.getContentPane().setLayout(GridBagLayout());
 

bERt0r

Top Contributor
Bevor du mit dem Gridbaglayout herumhantierst, weisst du überhaupt wie man mit einem BorderLayout umgeht? Du solltest erstmal die paar einfache Layoutmanager lernen.
 

hdi

Top Contributor
Dann mach dir ein neues JPanel p und ersetze in meinem Code jedes Vorkommen von frame.getContentPane() durch dieses p. Das p addest du dann ins frame per frame.getContentPane().add(p). Was dir das bringen soll verstehe ich allerdings nicht. Du hast dann einfach eine weitere Komponenten-Schicht auf dem Frame, die keine weitere Unterteilung vornimmt. Also unnötig.
 

markai

Aktives Mitglied
Dachte ich kriegs mit dem BorderLayout nicht so hin dass es aussieht wie ich will (siehe screenshot, letzter post) darum hab ichs gleich mit dem gridBagLayout versucht. Wär das besser geeignet?
 

hdi

Top Contributor
Sorry, mach mal die Augen auf:
Dein Content Pane könnte jetzt im einfachsten Fall ein BorderLayout haben. Allerdings scheint es ja dass das Button Panel die gesamte Höhe einnehmen soll. Beim BorderLayout wäre das nicht der Fall, da würde sich die untere Komponente (Image Panel) über die gesamte Breite legen.

GridBagLayout ist da also durchaus ne gute Wahl.
 

GUI-Programmer

Top Contributor
Wenn dir GridBagLayout nicht gefällt, kann ich dir nur FormLayout von jgoodies empfehlen. Das ist sehr ähnlich aufgebaut aber meiner Meinung nach leichter zu verwenden. Musst du halt selbst wissen, was dir besser liegt.
 

bERt0r

Top Contributor
Nicht so schnell erstmal. Der TO hat schon probleme damit ein vernünftiges BorderLayout anzuzeigen.
Mit Gridbag und Formlayout verwirrt ihr ihn nur mehr.
Versuchs doch einfach mal mit dem BorderLayout und schau was dabei rauskommt. Wenn du das richtig hinbekommst, fällts dir mit dem GridbagLayout garantiert leichter.
 

markai

Aktives Mitglied
Ich habs gestern dann doch noch mit dem GridBagLayout hinbekommen. Mein Fehler war glaub ich dass das JPanel zu groß war als dass es in meinen JFrame hineingepasst hätte. Hab meinen Frame dann größer gemacht und auf einmal war alles da. Hatte also im grunde eh (fast) alles richtig gemacht. Blöder Fehler eigentlich...

Wegen des JTrees: Das Programm soll dazu dienen älteren Menschen den Umgang mit einem Computer zu erleichtern. Meiner Erfahrung nach scheitert es oft daran, dass diese sich nicht vorstellen können wie eine Ordnerstruktur aufgebaut ist. Mit einem JTree hätten sie das gleiche Problem...

Danke an alle die mir geholfen haben :toll:
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
E JPanels auf gleicher Höhe (Y-Achse) in einem FlowLayout platzieren Java Basics - Anfänger-Themen 7
M Probleme beim aktualisieren eines JPanels Java Basics - Anfänger-Themen 7
V Alle Komponenten eines JPanels Java Basics - Anfänger-Themen 14
L Threads Laufbild Erzeugen Problem mit Aktualisieren des JPanels Java Basics - Anfänger-Themen 2
W 2 JPanels in 2Klasse in einem JFrame zusammenfügen Java Basics - Anfänger-Themen 12
D Methoden Implementieren von einer Zoomfunktion innerhalb eines JPanels mit null-Layoutmanager Java Basics - Anfänger-Themen 1
N Probleme beim entfernen eines JPanels Java Basics - Anfänger-Themen 4
L "Graphik" JPanels übereinander legen Java Basics - Anfänger-Themen 5
J Cannot find Symbol Variable mit JPanels Java Basics - Anfänger-Themen 2
M dynamische JPanels/Component Java Basics - Anfänger-Themen 3
M Überschreiben von JPanels funktioniert nicht! Java Basics - Anfänger-Themen 9
U Neuzeichnen eines JPanels Java Basics - Anfänger-Themen 17
A Mehere JPanels und JLabels - Warum Fehler? Java Basics - Anfänger-Themen 5
G Gesamten clickCount mehrerer JPanels herausfinden Java Basics - Anfänger-Themen 5
M JPanels vergleichen Java Basics - Anfänger-Themen 3
A Matisse oder Java Problem: JPanels werden riesig ? Java Basics - Anfänger-Themen 3
B LayoutManager Anorden von verschiedenen JPanels Java Basics - Anfänger-Themen 5
Q ActionListener event bei JPanels Java Basics - Anfänger-Themen 5
P Schriftgröße eines JPanels ändern Java Basics - Anfänger-Themen 2
T JPanels austauschen? Java Basics - Anfänger-Themen 4
T Fehlermeldung beim Klonen eines JPanels Java Basics - Anfänger-Themen 8
W JPanels löschen und neu konstruieren Java Basics - Anfänger-Themen 4
J Erste Schritte Arrays ineinander Verschachteln Java Basics - Anfänger-Themen 6
M Methoden void verschachteln Java Basics - Anfänger-Themen 4
S methoden verschachteln Java Basics - Anfänger-Themen 3
D GUIs ineinander verschachteln Java Basics - Anfänger-Themen 5
A Setter verschachteln? Java Basics - Anfänger-Themen 4
2 Kapselung Klassen verschachteln? Java Basics - Anfänger-Themen 3
G SQL ResultSets verschachteln Java Basics - Anfänger-Themen 5
G Layouts verschachteln Java Basics - Anfänger-Themen 17
Z Verschachteln mehrerer Arrays/Objekte (Telefonlisten) Java Basics - Anfänger-Themen 16

Ähnliche Java Themen

Neue Themen


Oben