Wieder ne Layout Frage

GUI-Programmer

Top Contributor
Ich habe ja bereits in einem anderen Thread, und zwar in Kurze Layout Frage danach gefragt, welches Layout man benutzen sollte, um einen einzelnen Komponenten mittig in ein Panel zu positionieren (hilfreichste Antwort von L-ectron-X: GridBagLayout).
Grund hierfür war, dass ich schon eine ganze Zeit lang versucht habe, Komponent an exakten Stellen (=Pixeln --> Koordinaten) zu positionieren, die sehr unterschiedlich sein sollen, ohne das NullLayout zu verwenden (Gründe hierfür sind wohl bekannt!). Hauptgrund war, dass ich nach dem Positionieren möchte, dass die Komponenten dennoch auf Größenveränderungen (z.B. bei Frame) reagieren.
Anfangs habe ich dies durch mühsame Berechnungen in der componentResized()-Methode auch erreicht (bie NullLayout). Jedoch ist auch dies eine schlechte Vorgehensweise.

Daher nun mein letzter Stand, um mein Vorhaben umzusetzen: jgoodies FormLayout
Beispiel:
Java:
import java.awt.EventQueue;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.ColumnSpec;
import com.jgoodies.forms.layout.RowSpec;

public class MyExample1 extends JPanel {
	protected JButton btnButton1, btnButton2;

	public MyExample1() {
		setPreferredSize(new Dimension(500, 350));
		setFormLayout(this, 500, 350);
		
		btnButton1 = new JButton("Button 1");
		btnButton1.setPreferredSize(new Dimension(180, 25));
		add(mittig(btnButton1), "101, 11, 180, 25, fill, fill");
		
		btnButton2 = new JButton("Button 2");
		btnButton2.setPreferredSize(new Dimension(160, 75));
		add(btnButton2, "301, 41, 160, 75, fill, fill");
		
	}
	
	private JPanel mittig(JComponent comp) {
		JPanel panel = new JPanel();
		panel.setOpaque(false);
		panel.setLayout(new GridBagLayout());
		panel.add(comp);
		return panel;
	}
	
	private void setFormLayout(JPanel panel, int width, int height) {
		ColumnSpec[] columnspec = new ColumnSpec[width];
		for(int i=0; i<columnspec.length; i++) {
			columnspec[i] = ColumnSpec.decode("1px:grow");
		}
		RowSpec[] rowspec = new RowSpec[height];
		for(int i=0; i<rowspec.length; i++) {
			rowspec[i] = RowSpec.decode("1px:grow");
		}
		panel.setLayout(new FormLayout(columnspec, rowspec));
	}
	
	private static void createFrame() {
		JFrame f = new JFrame("MyExample");
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		f.setContentPane(new MyExample1());
		f.pack();
		f.setVisible(true);
	}
	
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				createFrame();
			}
		});
	}
}

Nun meine Frage an euch: Gibt es bessere Möglichkeiten???
 
Ich nehme auch immer das jgoodies FormLayout und baue die UIs mit dem Abeille-Builder.

Die Konstruktion der GUI kann in XML oder in proprietären Binärdateien gespeichert werden und das Erzeugen der UI beschränkt sich auf wenige CodeZeilen:

Java:
class DeinPanel extends FormPanel 
	public DeinPanel (String s) {
		super(s);
	}
Laden der Gui-Definitionsdatei
Java:
DeinPanel deinPanel = new DeinPanel("resources/frm/GuiBeschreibung.xml");

Ich nehme keinen anderen Ansatz zur Erzeugung einer GUI mehr. Vielleicht ist das auch für Dich einen Versuch wert?
 
Also momentan benutze ich ja den WindowBuilder (Eclipse) und bin damit auch sehr zufrieden. Gibt es irgendwelch Alternativen zu den Abeile-Builder??? (Im Vergleich zum WindowBuilder viel zu klein!)

Und bitte noch mal meine ursprüngliche Frage beantworten!
 
Also ich nutze auch den WindowBuilderPro von Google, bin aber an GroupLayout Anhänger. Welches Layout du benutzt liegt im Endeffekt an deinen persönlichen Vorlieben. Die "besseren" Layoutmanager (forms, mig, group, gridbag) können eigentlich alles realisieren, es kommt nur darauf an wie viel Aufwand damit einhergeht.
Bezüglich deinem Problem mit den Pixelangeben: z.B im Grouplayout kannst du genau angeben, wieviele Pixel ein Component vom nächsten entfernt sein soll oder du fügst einen "Gap" ein, der quasi als Glue a la BoxLayout fungiert.
 
Schau dir doch einfach mal die Standard-Layouts mal an (da gibt es sogar FAQ-Beiträge dazu), dann weißt du auch, welches was kann und musst nicht jedes mal fragen.
 
Nun meine Frage an euch: Gibt es bessere Möglichkeiten???
Also ich finde das hier besser (erstellt mit MigLayout).
Ein paar Erläuterungen zur Instanziierung des Layouts:
Erster String: Parameter fürs ganze Layout: debug -> Zeichnen von nützlichen Hilfslinien, fill: zeit an dass der Container den gesamten zur Verfügung stehenden Platz beanspruchen soll.
Zweiter String: Parameter für die Spalten: die Komponenten in einer Spalte sollen mittig angeordnet sein
Dritter String: Parameter für die Zeilen. Aufgrund des fill-Parameters im ersten String werden die Zeilen und Spalten vergrössert, wenn das JPanel grösser wird, was wiederum der Fall ist wenn es direkt als Center im BorderLayout einer Content Pane eines JFrames angelegt ist.
Hier ist angegeben dass die erste Zeile nicht wachsen soll, und der ganze beim vergrössern zur Disposition stehden Platz der zweiten Zeilen zugeschlagen werden soll.
Java:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import net.miginfocom.swing.MigLayout;

public class CenteredButton{
	public static void main(String[] args){
		JFrame frame = new JFrame("Centered Button");
		JPanel panel = new JPanel(new MigLayout("debug, fill","center","[grow 0][align center, grow 100]"));
		JButton center = new JButton("Center");
		center.setPreferredSize(new Dimension(80,120));
		//Die erste Zeile erstreckt sich auch über die gesamte Breite des JPanels (fill-Parameter).
		// Hier wird festgelegt, dass die Komponente in der Zeile linksbündig positioniert werden soll
		// Mit wrap wird in die nächste Zeile umgebrochen
		panel.add(new JButton("Left aligned in First Row"), "align left, wrap");
		panel.add(center);
		//panel.add(new JButton("Centered 2"));
		frame.getContentPane().add(panel);
		frame.pack();
		frame.setVisible(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
}
 
Zuletzt bearbeitet:
@Harry Kane Und wenn ich jetzt 6, 7 weitere Komponent hätte, deren Koordinaten sehr verschieden wären und nur ein vergrößert/verkleinert werden soll, und ein anderer Teil nur wie in meinen Beispiel verschoben werden soll?
 
Die Frage ist ziemlich allgemein formuliert, was soll man genauer zu sagen?
Deshalb eine allgemeine Antwort:
MigLayout eignet sich zur Erstellung tabellenartiger Dialog, wobei in jeder Zelle eine oder mehrere Komponenten stehen können. Wenn eine tabellenartige Anordnung bei deinen "6,7 weiteren Komponenten" auch sinnvoll ist, und du eine Komponenten wachsen lassen möchtest wenn das JPanel grösser wird, musst du nur für die entsprechende Zelle in den Zeilen-und Spaltenparametern angeben dass sie wachsen soll, und du musst der Komponenten erlauben, dass sie "mit der Zelle wächst". Entferne mal die Kommentarzeichen in Zeile 17 vor
Java:
//panel.add(new JButton("Centered 2"));
und ersetze sie durch
Java:
panel.add(new JButton("Centered 2"), "grow");
 
Zuletzt bearbeitet:
Der WindowBuilder von Google ist auch gut. Ich habe mal zwei Versionen gebaut, die einen Button zentriert in einem Panel anzeigen und das auch auf Grössenänderungen reagiert.
Zunnächst der Code für den WindowBuilder:
Java:
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

import com.jgoodies.forms.factories.FormFactory;
import com.jgoodies.forms.layout.ColumnSpec;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.RowSpec;

@SuppressWarnings("serial")
public class Demo extends JPanel {

	/**
	 * Create the panel.
	 */
	public Demo() {
		setLayout(new FormLayout(new ColumnSpec[] {
				ColumnSpec.decode("default:grow"),
				FormFactory.RELATED_GAP_COLSPEC, FormFactory.DEFAULT_COLSPEC,
				FormFactory.RELATED_GAP_COLSPEC,
				ColumnSpec.decode("default:grow"), }, new RowSpec[] {
				FormFactory.GLUE_ROWSPEC, FormFactory.RELATED_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC, FormFactory.RELATED_GAP_ROWSPEC,
				FormFactory.GLUE_ROWSPEC, }));

		JButton btnZentriert = new JButton("Zentriert");
		add(btnZentriert, "3, 3, fill, fill");

	}

	public static void main(String[] args) {
		JFrame frame = new JFrame("Demo");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.add(new Demo());
		frame.pack();
		frame.setVisible(true);
	}
}
Und für Abeille:
Java:
import javax.swing.JFrame;

import com.jeta.forms.components.panel.FormPanel;

@SuppressWarnings("serial")
public class Abeille extends FormPanel{

	public Abeille(String panel) {
		super(panel);
	}

	public static void main(String[] args) {
		JFrame frame = new JFrame("Demo");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.add(new Abeille("panel.xml"));
		frame.pack();
		frame.setVisible(true);

	}

}

Hier steckt der ganze GUI-Beschreibung in der panel.xml-Datei. Hier ist der Inhalt:
[XML]
<?xml version="1.0" encoding="UTF-8"?>

<object classname="com.jeta.forms.store.memento.FormPackage">
<at name="fileversion">
<object classname="com.jeta.forms.store.memento.FormsVersion2">
<at name="major">2</at>
<at name="minor">0</at>
<at name="sub">0</at>
</object>
</at>
<at name="form">
<object classname="com.jeta.forms.store.memento.FormMemento">
<super classname="com.jeta.forms.store.memento.ComponentMemento">
<at name="cellconstraints">
<object classname="com.jeta.forms.store.memento.CellConstraintsMemento">
<at name="column">1</at>
<at name="row">1</at>
<at name="colspan">1</at>
<at name="rowspan">1</at>
<at name="halign">default</at>
<at name="valign">default</at>
<at name="insets" object="insets">0,0,0,0</at>
</object>
</at>
<at name="componentclass">com.jeta.forms.gui.form.FormComponent</at>
</super>
<at name="id">Vfe94839G1337dfa51c6FU8000</at>
<at name="rowspecs">CENTER😀EFAULT:GROW(1.0),CENTER😀EFAULT:NONE,CENTER😀EFAULT:GROW(1.0)</at>
<at name="colspecs">FILL😀EFAULT:GROW(1.0),FILL😀EFAULT:NONE,FILL😀EFAULT:GROW(1.0),FILL😀EFAULT:NONE</at>
<at name="components">
<object classname="java.util.LinkedList">
<item >
<at name="value">
<object classname="com.jeta.forms.store.memento.BeanMemento">
<super classname="com.jeta.forms.store.memento.ComponentMemento">
<at name="cellconstraints">
<object classname="com.jeta.forms.store.memento.CellConstraintsMemento">
<at name="column">2</at>
<at name="row">2</at>
<at name="colspan">1</at>
<at name="rowspan">1</at>
<at name="halign">default</at>
<at name="valign">default</at>
<at name="insets" object="insets">0,0,0,0</at>
</object>
</at>
<at name="componentclass">com.jeta.forms.gui.form.StandardComponent</at>
</super>
<at name="jetabeanclass">com.jeta.forms.gui.beans.JETABean</at>
<at name="beanclass">javax.swing.JButton</at>
<at name="beanproperties">
<object classname="com.jeta.forms.store.memento.PropertiesMemento">
<at name="classname">javax.swing.JButton</at>
<at name="properties">
<object classname="com.jeta.forms.store.support.PropertyMap">
<at name="text">Zentriert</at>
<at name="height">23</at>
<at name="width">77</at>
<at name="name"></at>
<at name="actionCommand">Zentriert</at>
<at name="border">
<object classname="com.jeta.forms.store.properties.CompoundBorderProperty">
<super classname="com.jeta.forms.store.properties.BorderProperty">
<at name="name">border</at>
</super>
<at name="borders">
<object classname="java.util.LinkedList">
<item >
<at name="value">
<object classname="com.jeta.forms.store.properties.DefaultBorderProperty">
<super classname="com.jeta.forms.store.properties.BorderProperty">
<at name="name">border</at>
</super>
</object>
</at>
</item>
</object>
</at>
</object>
</at>
</object>
</at>
</object>
</at>
</object>
</at>
</item>
</object>
</at>
<at name="properties">
<object classname="com.jeta.forms.store.memento.PropertiesMemento">
<at name="classname">com.jeta.forms.gui.form.GridView</at>
<at name="properties">
<object classname="com.jeta.forms.store.support.PropertyMap">
<at name="name"></at>
<at name="fill">
<object classname="com.jeta.forms.store.properties.effects.PaintProperty">
<at name="name">fill</at>
</object>
</at>
<at name="scollBars">
<object classname="com.jeta.forms.store.properties.ScrollBarsProperty">
<at name="name">scollBars</at>
<at name="verticalpolicy">21</at>
<at name="horizontalpolicy">31</at>
</object>
</at>
<at name="border">
<object classname="com.jeta.forms.store.properties.CompoundBorderProperty">
<super classname="com.jeta.forms.store.properties.BorderProperty">
<at name="name">border</at>
</super>
<at name="borders">
<object classname="java.util.LinkedList"/>
</at>
</object>
</at>
</object>
</at>
</object>
</at>
<at name="cellpainters">
<object classname="com.jeta.forms.store.support.Matrix">
<at name="rows">
<object classname="[Ljava.lang.Object;" size="3">
<at name="item" index="0">
<object classname="[Ljava.lang.Object;" size="4"/>
</at>
<at name="item" index="1">
<object classname="[Ljava.lang.Object;" size="4"/>
</at>
<at name="item" index="2">
<object classname="[Ljava.lang.Object;" size="4"/>
</at>
</object>
</at>
</object>
</at>
<at name="rowgroups">
<object classname="com.jeta.forms.store.memento.FormGroupSet">
<at name="groups">
<object classname="java.util.HashMap"/>
</at>
</object>
</at>
<at name="colgroups">
<object classname="com.jeta.forms.store.memento.FormGroupSet">
<at name="groups">
<object classname="java.util.HashMap"/>
</at>
</object>
</at>
</object>
</at>
</object>
[/XML]
 

Zurück
Oben