Java GridBagLayout: Simple, aber äußerst knifflige Anordnung gewünscht.

T

Tersus

Gast
Guten Abend,

ich stelle mich irgendwie etwas ungeschickt an. Ich habe zwei Bilder bereit gestellt, die zeigen, wie ich die Anordnung gerne hätte.

Kurze Info:
- Frame verwendet das GridBagLayout
- Frame entgält 2 Panels (schwarz und cyan)
- oberes Panel (cyan) verwendet das Standard Flowlayout
- oberes Panel (cyan) enthält zwei Buttons


Das erste Bild zeigt das Fenster bei 400x400 Pixel. Wenn ich es dünner ziehe, soll sich das untere Panel (schwarzer Hintergrund) entsprechend an die maximale Breite und Höhe des Frames anpassen.
Das obere Panel (cyaner Hintergrund) soll sich auch anpassen, aber nicht im selben Verhältnis, wie das untere, ausbreiten, sondern lediglich so viel, wie die Buttons bei neuer Anordnung (untereinander, wegen Platzmangel) Platz brauchen.
Bild zwei zeigt das Fenster bei 150x400 Pixel und wie es nach dieser Verdünnerung des Frames aussehen sollte.

Wie läßt sich das realisieren?

EDIT
Die zweite Miniaturansicht sollte eigentlich an erster Stelle stehen und die erste entsprechend an zweiter.
 

Anhänge

  • Fall_2.png
    Fall_2.png
    2,3 KB · Aufrufe: 201
  • Fall_1.png
    Fall_1.png
    2,8 KB · Aufrufe: 229
Okay, wenn ich das richtig verstehe möchtest du den Status von Bild 1, also dem 150x400px erreichen, dass es so aussieht.

Ich würde gerne mal deinen Quellcode sehen, denn dass die Buttons untereinander stehen, macht das FlowLayout normalerweise von selbst. Was geschieht denn im Moment wenn du das Fenster verkleinerst?
Sollte eigentlich kein großes Problem sein, auch dass das untere Panel mitwächst, da ist das GridBagLayout sehr fähig was das angeht.

Also mit Quellcode von dir lässt sich das bestimmt leicht aufklären

Gruß Hardliner
 
Oh, jetzt bin ich echt gespannt. :D Ich glaube nicht, dass das so einfach ist.

Hier mein Quelltext, welcher ein Fenster dem zweite Bild (400x400 Pixel) im Eigensbeitrag entsprechend erzeugt.

Code:
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Panel;

import javax.swing.JButton;

public class gbo extends Frame{

	private static final long serialVersionUID = 1L;

	public gbo() {
		
		setLayout(new GridBagLayout());

		initOberesPanel();
		initUnteresPanel();

		setSize(400, 400);

	}
		
	private void initOberesPanel() {		
		
		Panel objekt_Panel = new Panel();
		objekt_Panel.setBackground(Color.cyan);

		objekt_Panel.add(new JButton("----------"));
		objekt_Panel.add(new JButton("----------"));

		// LayoutRichtlienien für das obere Panel

		GridBagConstraints objekt_GridBagConstraints = new GridBagConstraints();
		objekt_GridBagConstraints.fill = GridBagConstraints.BOTH;
		objekt_GridBagConstraints.gridx = 0;
		objekt_GridBagConstraints.gridy = 0;
		
		add(objekt_Panel, objekt_GridBagConstraints);
		
	}

	private void initUnteresPanel(){

		Panel objekt_Panel = new Panel();
		objekt_Panel.setBackground(Color.black);

		// LayoutRichtlienien für das untere Panel

		GridBagConstraints objekt_GridBagConstraints = new GridBagConstraints();
		objekt_GridBagConstraints.fill = GridBagConstraints.BOTH;
		objekt_GridBagConstraints.gridx = 0;
		objekt_GridBagConstraints.gridy = 1;
		objekt_GridBagConstraints.weightx = 1;
		objekt_GridBagConstraints.weighty = 1;
		
		add(objekt_Panel, objekt_GridBagConstraints);

	}

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

}

Zieht man dieses Fenster kleiner, so ordnet sich der rechte JButton im oberen Panel nicht neu an. Er soll sich aber neu anordnen, bzw. unter dem ersten positionieren.

Die Ergänzung

Code:
		objekt_GridBagConstraints.weightx = 1;
		objekt_GridBagConstraints.weighty = 1;

auch für das erste GridBagConstraints führt nicht zum gewünschten Ergebnis, da dann das obere Panel dann stets so groß ist, wie das untere.
 
Okay, zuerst mal empfehle ich dir Swing zu verwenden, das heißt:

Frame wird zu JFrame,
Panel zu JPanel.

In Zeile 16 setzt du das Grund-Layout auf ein Gridbag-Layout... das wird aber nie verwendet.
Bei einem Fenster platzierst du die Komponenten normalerweise auf dem Content-Pane.

Das kannst du entweder über getContentPane() aufrufen oder ein JPanel erstellen und über setContentPane(dieses JPanel) definieren.

nennen wir das ab hier: myContentPane.

dann setzt du das GridBagLayout als Layout für das myContentPane (später musst du dann dein oberes und unteres panel auf das myContentpane adden entsprechend (Z. 40 bzw. 58).

Jetzt noch zu deiner letzten Anmerkung. Das weightx und weighty (in deinem Fall nur weighty wichtig) definiert quasi wie stark welches Panel wächst wenn du ziehst. Das heißt für das obere Panel setzt du weighty auf 0, für das untere auf 1 (also 0% oben, 100% unten).

Ich kann den Code gerade leider nicht testen weil ich keine IDE greifbar habe, aber wenn du dann sagst es funktioniert immernoch nicht, paste nochmal deinen aktuellen Code und ich seh mir das mal live an.

Gruß Hardliner

EDIT:

GridBagLayout gridBagLayout = new GridBagLayout();
gridBagLayout.rowWeights = new double[]{0.0, 1.0};
gridBagLayout.columnWeights = new double[]{1.0};

Das fehlt noch, danach funktioniert es bei mir
 
Zuletzt bearbeitet: (Code getestet)
Nein, funktioniert bei mir nicht.

Hier der Code:

Code:
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

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

public class gbo extends JFrame{
	
	private static final long serialVersionUID = 1L;
	private GridBagLayout gbl;
	
	public gbo() {
		
		gbl	= new GridBagLayout();
		
		gbl.rowWeights		= new double[]{0.0, 1.0};
		gbl.columnWeights	= new double[]{1.0};
				
		initOberesPanel();
		initUnteresPanel();

		setSize(400, 400);
		
		getContentPane().setLayout(gbl);

	}
		
	private void initOberesPanel() {		
		
		JPanel objekt_JPanel = new JPanel();
		objekt_JPanel.setBackground(Color.cyan);
//		objekt_Panel.setLayout(new FlowLayout(FlowLayout.LEFT));

		objekt_JPanel.add(new JButton("----------"));
		objekt_JPanel.add(new JButton("----------"));

		// LayoutRichtlienien für das obere Panel

		GridBagConstraints objekt_GridBagConstraints = new GridBagConstraints();
		objekt_GridBagConstraints.fill = GridBagConstraints.BOTH;
		objekt_GridBagConstraints.gridx = 0;
		objekt_GridBagConstraints.gridy = 0;
		objekt_GridBagConstraints.weighty = 0;
		
		gbl.setConstraints(objekt_JPanel, objekt_GridBagConstraints);
		getContentPane().add(objekt_JPanel); //, objekt_GridBagConstraints);
		
	}

	private void initUnteresPanel(){

		JPanel objekt_JPanel = new JPanel();
		objekt_JPanel.setBackground(Color.black);

		// LayoutRichtlienien für das untere Panel

		GridBagConstraints objekt_GridBagConstraints = new GridBagConstraints();
		objekt_GridBagConstraints.fill = GridBagConstraints.BOTH;
		objekt_GridBagConstraints.gridx = 0;
		objekt_GridBagConstraints.gridy = 1;
		objekt_GridBagConstraints.weighty = 1;
		
		gbl.setConstraints(objekt_JPanel, objekt_GridBagConstraints);
		getContentPane().add(objekt_JPanel); //, objekt_GridBagConstraints);
		
	}

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

}
 
Zeile 26 über initoberesPanel() und 47 wieder in 48 bzw 65 in 66 wie vorher, das sollte alles sein
 
So wie ich das sehe, wird dein Vorhaben mit der alleinigen Nutzung von GridBagLayout und FlowLayout nicht funktionieren.

Das liegt daran, dass das FlowLayout ein doch recht merkwürdiges Konstrukt ist.

Ein Layout-Manager im Allgemeinen hat ja zwei Aufgaben:
1. Die "preferred size" eines Containers ausrechnen
2. Die Komponenten in einem Container anhand bestimmer Regeln ausrichten

FlowLayout erfüllt erst einmal beide Aufgaben, jedoch nicht besonders klug.

Die Methode zum Berechnen der bevorzugten Größe geht nämlich immer davon aus, dass die Komponenten in einer einzigen Reihe angeordnet werden. Das hat zur Folge, dass obwohl der Code zur Ausrichtung klug genug ist um die Komponenten in mehreren Reihen anzuordnen, immer nur die oberste Zeile angezeigt wird.

Das wird dann deutlich, wenn das FlowLayout nach unten hin mehr Platz hat als die getPreferredSize()-Methode angibt. Nur dann werden nämlich ohne Probleme alle Komponenten auch in mehreren Reihen angezeigt.

Um jetzt dein Problem anzugehen: Rob Camick hat einen recht hübschen LayoutManager namens "Wrap Layout" geschrieben, der eigentlich genau so funktioniert, wie man es normalerweise vom FlowLayout vermuten würde.

Hier der direkte Link zur WrapLayout.java: Link
Und hier der Link zu seinem Artikel dazu: Link

Ich denke, dass sollte dir weiterhelfen!

Abschließend noch eine Bitte an Hardliner93: Falls du es wirklich geschafft hast, das gewünschte Verhalten nur mit dem FlowLayout zu realisieren, würde mich dein benutzter Code sehr interessieren!
 
damit meine ich, vor dem Aufruf von initOberesPanel() das Layout des contentPane auf dein GridBagLayout zu setzen, also den Aufruf von

getContentPane().setLayout(gbl);

schon in Zeile 20.
Und das was du in den Zeilen von getContentPane().add(...) auskommentiert hast (Z. 48, 46) war schon richtig so. Die Zeilen darüber sind nicht notwendig (also das gbl.setConstraints(...) kannst du weglassen

@Killkrog
Code:
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

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

public class gbo extends JFrame {

	private static final long serialVersionUID = 1L;

	public gbo() {
		GridBagLayout gridBagLayout = new GridBagLayout();
		gridBagLayout.rowWeights = new double[]{0.0, 1.0};
		gridBagLayout.columnWeights = new double[]{1.0};
		getContentPane().setLayout(gridBagLayout);

		initOberesPanel();
		initUnteresPanel();

		setSize(400, 400);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);	
	}

	private void initOberesPanel() {
		JPanel objekt_Panel = new JPanel();
		objekt_Panel.setBackground(Color.cyan);

		objekt_Panel.add(new JButton("----------"));
		objekt_Panel.add(new JButton("----------"));

		// LayoutRichtlienien für das obere Panel

		GridBagConstraints objekt_GridBagConstraints = new GridBagConstraints();
		objekt_GridBagConstraints.fill = GridBagConstraints.BOTH;
		objekt_GridBagConstraints.gridx = 0;
		objekt_GridBagConstraints.gridy = 0;
		objekt_GridBagConstraints.weighty = 0.1;
		getContentPane().add(objekt_Panel, objekt_GridBagConstraints);
	}

	private void initUnteresPanel() {

		JPanel objekt_Panel = new JPanel();
		objekt_Panel.setBackground(Color.black);

		// LayoutRichtlienien für das untere Panel

		GridBagConstraints objekt_GridBagConstraints = new GridBagConstraints();
		objekt_GridBagConstraints.fill = GridBagConstraints.BOTH;
		objekt_GridBagConstraints.gridx = 0;
		objekt_GridBagConstraints.gridy = 1;
		objekt_GridBagConstraints.weighty = 1;
		getContentPane().add(objekt_Panel, objekt_GridBagConstraints);

	}

	public static void main(String[] args) {
		gbo fenster = new gbo();
		fenster.setVisible(true);
	}
}
 
Dachte ich's mir ;)

Wenn du dir einmal genau die Hintergründe der Panels ansiehst, wirst du erkennen, dass das obere Panel immer die selbe Größe hat bei dir. Das heisst, wenn die zwei Buttons nebeneinander passen, verschwendest du Platz nach unten.

Laut erstem Post im Thread soll sich die Größe des oberen Panels aber automatisch an die Anzahl der Zeilen anpassen.

Ich halte daher an meiner Meinung fest, dass das gewünschte Verhalten mit GridBag- und FlowLayout nicht erreichbar ist.
 
Okay danke für die Info, hatte ich dann wohl bisschen anders verstanden...
In diesem Fall stimme ich dir zu, dass ich auch keinen weiteren Weg kennen würde, war mir nicht aufgefallen dass die Größe von Anfang auf die beiden Buttons ausgelegt ist.
 
Zurück
Oben