Swing suche passenden LayoutManager

TheWhiteShadow

Bekanntes Mitglied
Hallo zusammen,

ich suche ein LayoutManager für folgendes Problem:

Ich hab ein JPanel mit mehreren verschieden-viel und -große Elementen in einer JScrollPane.
Die JScrollPane hat eine feste Größe. Die Elemente nicht.
Die Elemente sollen als eine Liste von oben nach unten angezeigt werden.

Folgende Versuche hab ich bereits gemacht:
FlowLayout: wäre super, wenn es von oben nach unten ginge. Tut es aber nicht.
BoxLayout: Zentriert die Elemente, wenns zu wenig sind.
GridBagLayout: gleiches Problem. anchor=NORTH funktionierte nicht.
GridLayout: nur für gleichgroße Elemente.

Eine Glue-Komponente wollte auch nicht so richtig.
Hab die Elemente als auch das JPanel mit TOP_ALIGNMENT versehen.

Muss ich jetzt tatsächlich ein eigenen LayoutManager für ne einfache Liste schreiben?
Das kann doch nicht sein. Da muss es doch noch was geben, was ich übersehen hab.
 
Ich glaube dass man nur in sehr speziellen Fällen einen eigenen LayoutManager schreiben muss. Es gibt neben den Standard-Swing-LayoutManagern auch ein paar freie, die man sich mal anschauen kann, z.B. TableLayout oder FormLayout.
Was du beschreibst klingt jedoch so, als könne man es z.B. mit einem GridBagLayout oder einem GroupLayout hinbekommen. Beide nicht völlig intuitiv aber durchaus potent und es Bedarf nicht selten etwas Propiererei bis man sein Ziel hat.

In vielen Fällen werden Layouts auch kombiniert. Zum Beispiel für die horizontalen Elemente ein JPanel mit FlowLayout, für die vertikalen dann ein BoxLayout mit jenen Panels.

Wenn du eine Skizze von deiner Wunschmaske abliefern kannst bin ich sicher, dass es den einen oder andern Forenleser reizt ein paar Codevorschläge zu posten 🙂
 
Eigentlich hab ich selten Probleme mit Layouts, aber heute will es einfach nicht.

So sol es in etwa aussehen (JScrollPane ist nicht ganz ausgefüllt):
unbenantttnt1.png


Bei bisher allen Layouts, die eine vertikale Auflistung hinbekommen haben, wurden die Elemente im blauen Bereich Zentriert dargestellt, was nicht gewollt ist.

GridBagLayout hat wie bereits erwänt nicht so funktioniert wie gewollt.
GroupLayout brachte übrigens das Gleiche.
Kombinieren kann man da nicht viel.
FormLayout, TableLayout. Das hört sich so an, als wären die ähnlich dem GridBagLayout.
 
Wenn dich FlowLayout glücklich gemacht hat: man kann es auch vertikal einstellen, siehe die Konstruktoren.

P.S.
Ist das ungefähr das, was du haben wolltest?
Java:
public class PanelScrollTest {

public static void main(String[] args) {
		JFrame frame = new JFrame();
		frame.setSize(200, 500);
		JPanel panel = new JPanel();
		panel.setLayout(new GridBagLayout());
		panel.setBackground(Color.CYAN);
		addSomeComponents(panel);
		JScrollPane scrollPane = new JScrollPane(panel);
		frame.add(scrollPane);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
	}

	public static void addSomeComponents(JPanel panel) {
		Random numGen = new Random();
		for (int i = 0; i < 10; i++) {
			GridBagConstraints gbc = new GridBagConstraints();
			gbc.insets = new Insets(10, 10, 10, 10);
			gbc.fill = GridBagConstraints.HORIZONTAL;
			gbc.weightx = 1f;
			gbc.gridy = i;
			JPanel comp = new JPanel();
			comp.setBackground(new Color(numGen.nextInt(256), numGen
					.nextInt(256), numGen.nextInt(256)));
			comp.setPreferredSize(new Dimension(100, numGen.nextInt(300) + 20));
			panel.add(comp, gbc);
		}
	}
}
 
Zuletzt bearbeitet:
Abgesehen davon, dass dein Fenster herlich bunt ist^^ zeigt es den gleichen Fehler, den ich auch hab.
bei 2-3 Elementen ist die Fläche nämlich nicht ausgefüllt und die Elemente zentriert, was ich vermeiden wollte.

sieh hier:
unbenareennt.png


Wenn dich FlowLayout glücklich gemacht hat: man kann es auch vertikal einstellen, siehe die Konstruktoren.

Hab alle Konstanten duchprobiert. Ohne Erfolg.

Edit: Das Layout hier ist perfekt.
http://www.java-forum.org/awt-swing-swt/73452-flowlayout-alternative.html#post451696
 
Zuletzt bearbeitet:
Falls es dir hilft, der selbe Anwendungsfall war der Hauptgrund warum ich mich ins Grouplayout eingearbeitet habe. Das geht damit nämlich sehr gut.
Java:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;

import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.EmptyBorder;
import javax.swing.border.EtchedBorder;


public class VerticalFlow extends JFrame {

	private JPanel contentPane;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					VerticalFlow frame = new VerticalFlow();
					frame.setVisible(true);
					frame.pack();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public VerticalFlow() {
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 450, 348);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
		
		JScrollPane scrollPane = new JScrollPane();
		scrollPane.setPreferredSize(new Dimension(200, 600));
		contentPane.add(scrollPane);
		
		JPanel panel = new JPanel();
		scrollPane.setViewportView(panel);
		
		JPanel panel_1 = new JPanel();
		panel_1.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null));
		panel_1.setBackground(Color.YELLOW);
		panel_1.setPreferredSize(new Dimension(100, 50));
		
		JPanel panel_2 = new JPanel();
		panel_2.setPreferredSize(new Dimension(100, 100));
		panel_2.setBackground(Color.RED);
		panel_2.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null));
		
		JPanel panel_3 = new JPanel();
		panel_3.setBackground(Color.GREEN);
		panel_3.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null));
		panel_3.setPreferredSize(new Dimension(150, 300));
		GroupLayout gl_panel = new GroupLayout(panel);
		gl_panel.setAutoCreateGaps(true);
		gl_panel.setAutoCreateContainerGaps(true);
		gl_panel.setHorizontalGroup(
			gl_panel.createParallelGroup(Alignment.CENTER)
				.addComponent(panel_1, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
				.addComponent(panel_2, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
				.addComponent(panel_3, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
		);
		gl_panel.setVerticalGroup(
			gl_panel.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_panel.createSequentialGroup()
					.addComponent(panel_1, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
					.addComponent(panel_2, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
					.addComponent(panel_3, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
		);
		panel.setLayout(gl_panel);
	}

}
 
Das GroupLayout ist nicht schlecht, gerade für komplexere Anordungsmodelle, aber erfordert extrem viel Code, ist unübersichtlich und ich hab mich noch nicht so sehr darin eingearbeitet.
Versucht hatte ich es, aber mir fehle vermutlich:
Java:
addComponent(panel_1, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE);

Meißtens hat das GridBagLayout ja ausgereicht welches wenigstens durch die GridBagConstraints eine kurze übersichtliche Syntax hat.

Für eine Anordnung ähnlich dem FlowLayout sind mMn beide Manager unpraktisch.
 
Schau dir mal Forms Layout an. Damit gehts extrem einfach und die API ist gut beschrieben. Hier im Forum gibts dazu auch shcon einige Threads.
 
Meißtens hat das GridBagLayout ja ausgereicht welches wenigstens durch die GridBagConstraints eine kurze übersichtliche Syntax hat.
MMn sind die GridBagConstraints das unübersichtlichste und klobigste in der standard JavaAPI. Und bezüglich Codelänge ist das GroupLayout um 2 Zeilen Länger (bzgl. Layout Code, das sind nur 16 Zeilen). Im gridbagLayout brauchst du mindestens 2 Zeilen Code pro Component, normalerweise aber eher so um die 5-6. Im GroupLayout kommst du immer mit 2 aus.

Für eine kleine Einführung ins GroupLayout schau dir mal diesen Thread an: http://www.java-forum.org/awt-swing-swt/127923-grouplayout.html
Ich glaube ich sollte mal ein Tutorial fürs GroupLayout schreiben, das wird von vielen einfach missverstanden. WindowProBuilder z.b erzeugt katastrophale Ergebnisse mit dem GroupLayout, weil er die Sache viel zu kompliziert angeht. Du kannst dier das Grouplayout wie ein <table> in html vorstellen. Die <tr> Elemente sind die Groups, die <td> Elemente die Componenten. Der Unterschied der viele verwirrt ist, dass die <tr> Elemente sowohl Zeilen als auch Spalten sein können - es bleibt dir überlassen wie du es aufziehst. Die meisten GUIs lassen sich aber einfach nach einem Tabellenmuster aufbauen.
 
Zuletzt bearbeitet:

Neue Themen


Zurück
Oben