LayoutManager Probleme mit Positionierung/Abständen der Komponenten

Bitte aktiviere JavaScript!
Hallo liebe Community,
da ich sehr häufig bei der Erstellung von GUIs meine Probleme habe, beschleicht mich doch das Gefühl, dass ich bei der Verwendung der verschiedenen LayoutManager etwas grundlegend falsch verstehe. Daher hoffe ich auf ein wenig generelle Hilfe an einem konkreten Beispiel/Problem mit der Bitte auf Hinweise, was ich hier grundsätzlich falsch mache bzw. warum die GUI so angezeigt wird, wie sie angezeigt wird :confused:

Also zum konkreten Projekt: Ich verwende ein JFrame auf welchem als grundlegender LayoutManager ein BorderLayout zum Einsatz kommt. Im Center-Part befinden sich die meisten Komponenten (und werden sogar so angezeigt, wie ich das will :)). Der LineEnd-Part enthält ein Panel (welches im konkreten Projekt wahlweise angezeigt wird oder auch nicht). Hier sollen neben ein paar Buttons in gitterförmiger Struktur JSpinner angezeigt werden. Die Wahl fiel auf ein GridLayout. Aufgebaut habe ich das mit dem unten stehenden Quelltext..
Das Problem: Zwischen den Buttons (oben) und den JSpinnern (unten) befindet sich ein so großer Abstand, dass die Spinner nicht mehr passen und auch zu klein dargestellt werden (siehe auch Bild).. Hier frage ich mich tatsächlich: Warum?

Java:
import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.Dimension;

public class TestView extends JFrame {
 
  public TestView() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    init();
    setVisible(true);
  }
 
  public void init() {
    setPreferredSize(new Dimension(300,300));
    
    JPanel panel1 = new JPanel();
    JPanel panel2 = new JPanel();
    JPanel panel3 = new JPanel();
    JPanel panel4 = new JPanel();
    
    panel1.setLayout(new BorderLayout());
    panel2.setLayout(new GridLayout(0,1));
    //panel3 bleibt beim Standard-FlowLayout
    panel4.setLayout(new GridLayout(0,3,10,10));
    
    for (int i=0;i<10;i++) {
      panel4.add(new JSpinner());
      panel4.add(new JLabel("bis"));
      panel4.add(new JSpinner());
    } // end of for
    
    panel3.add(new JButton("Button a"));
    panel3.add(new JButton("Button b"));
    
    panel2.add(panel3);
    panel2.add(panel4);
    
    panel1.add(new JButton("Viel Content"), BorderLayout.CENTER);
    panel1.add(panel2, BorderLayout.LINE_END);
    
    getContentPane().add(panel1);
 
    pack();
    
    
  } 
}
 

Anhänge

A

Anzeige


Vielleicht hilft dir dieser Kurs hier weiter: (hier klicken)
Hier frage ich mich tatsächlich: Warum?
Dein panel2 verwendet ein GridLayout, bei dem alle Komponenten in einem Gitter mit Zellen gleicher Größe angeordnet werden. Damit werden panel3 und panel4 gleich groß. Der Leerraum entsteht dann durch die Verwendung von FlowLayout in panel3, da dieses Layout den Platz nicht füllt, sondern eben leer lässt.
 
Damit werden panel3 und panel4 gleich groß.
Oh, je. Genau das hatte ich natürlich nicht berücksichtigt. Vielen Dank.
Dann ist die Korrektur ja ganz simpel: Statt für panel2 ein GridLayout zu verwenden kommt ein BoxLayout zum Einsatz:
Code:
panel2.setLayout(new BoxLayout(panel2, BoxLayout.Y_AXIS));
Passt nun auch soweit. Eine Sache verwundert mich dann allerdings noch. Sobald ich das Fenster vergrößere und es größer wird, als benötigt, wächst der Platz zwischen den Buttons und den Spinnern (ähnlich wie beim GridLayout). Die Dokumentation besagt aber:
When a BoxLayout lays out components from top to bottom, it tries to size each component at the component's preferred height. If the vertical space of the layout does not match the sum of the preferred heights, then BoxLayout tries to resize the components to fill the space. The components either grow or shrink to fill the space, with BoxLayout honoring the minimum and maximum sizes of each of the components. Any extra space appears at the bottom of the container.
Also müsste ich doch davon ausgehen, dass der freie Platz unten erscheint?? Auch das Einfügen eines VerticalGlue wirkt nur bedingt..
 
BoxLayout tries to resize the components to fill the space. The components either grow or shrink to fill the space, with BoxLayout honoring the minimum and maximum sizes of each of the components. Any extra space appears at the bottom of the container.
Du hast die Antwort hier schon zitiert :) Das BoxLayout vergrößert die Komponenten bis zu ihrer maximum size. Wenn danach immer noch Platz übrig ist, wird der unten angefügt.

Sprich:
Java:
panel3.setMaximumSize(panel3.getPreferredSize());
panel4.setMaximumSize(panel4.getPreferredSize());
sollte helfen.
 
Das BoxLayout vergrößert die Komponenten bis zu ihrer maximum size.
Ah ok, das leuchtet ein. Deine Lösung funktioniert auch soweit. Nur eine Sache scheint mir immer noch nicht ganz klar: Beim Vergrößern des Frames werden die Spinner auch vergrößert. War mir klar, weil ich zunächst die Size von Panel 4 unangetastet ließ. Dann habe ich die maximumSize der einzelnen Spinner gesetzt (vor allem die Höhe) und trotzdem wird die Größe auch oberhalb dieser maxSize gesetzt? Achtet BoxLayout nun doch nicht die maxSize aller Komponenten oder nur des Panels??
 
Es geht prinzipiell immer um die direkten Kindkomponenten. Um die Kindeskinder müssen sich die Kinder kümmern :) Allerdings kann ich das Problem grad nicht nachvollziehen, hast Du mal ein lauffähiges Beispiel? Wird aber ein wenig dauern, bis ich darauf antworte.
 
hast Du mal ein lauffähiges Beispiel?
Klar, hat sich an sich nicht viel geändert ;)
Java:
import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.Dimension;
import java.awt.event.*;

public class TestView extends JFrame {
    
  public TestView() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    init();
    setVisible(true);
  }
 
  public void init() {
    setPreferredSize(new Dimension(600,600));
    
    JPanel panel1 = new JPanel();
    JPanel panel2 = new JPanel();
    JPanel panel3 = new JPanel();
    JPanel panel4 = new JPanel();
    
    
    
    panel1.setLayout(new BorderLayout());
    panel2.setLayout(new BoxLayout(panel2, BoxLayout.Y_AXIS));
    //panel3 bleibt beim Standard-FlowLayout
    panel4.setLayout(new GridLayout(0,3,10,10));
    
    
    for (int i=0;i<10;i++) {
      JSpinner a = new JSpinner();
      a.setMaximumSize(new Dimension((int)a.getMaximumSize().getWidth(),(int)a.getPreferredSize().getHeight()));
      panel4.add(a);
      panel4.add(new JLabel("bis"));
      JSpinner b = new JSpinner();
      b.setMaximumSize(new Dimension((int)b.getMaximumSize().getWidth(),(int)b.getPreferredSize().getHeight()));
      panel4.add(b);
    } // end of for
    
    panel3.add(new JButton("Button a"));
    panel3.add(new JButton("Button b"));
    
    panel3.setMaximumSize(panel3.getPreferredSize());
    //panel4.setMaximumSize(panel4.getPreferredSize());
    
    panel2.add(panel3);
    panel2.add(panel4);
    
    panel2.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
    
    panel1.add(new JButton("Viel Content"), BorderLayout.CENTER);
    panel1.add(panel2, BorderLayout.LINE_END);
    
    getContentPane().add(panel1);
 
    pack();

    
  } 
}
 
Ja, ist klar: wenn panel4 vergrößert wird, dann schlägt für die Komponenten im panel4 das GridLayout zu. Für panel2 (BoxLayout) ist nur die maximum size von panel4 relevant, nicht die Größen der Komponenten im panel4.
 
dann schlägt für die Komponenten im panel4 das GridLayout zu
o_O Ich fühl mich grad echt blöd.. Danke für die Aufklärung.
Demnach schert sich das GridLayout nicht um die eingestellten Größen der Spinner-Komponenten. Kann man dieses Layout irgendwie dazu überreden, oder müsste dann ein gänzlich anderer Ansatz gewählt werden?
 
o_O Ich fühl mich grad echt blöd.. Danke für die Aufklärung.
Demnach schert sich das GridLayout nicht um die eingestellten Größen der Spinner-Komponenten. Kann man dieses Layout irgendwie dazu überreden, oder müsste dann ein gänzlich anderer Ansatz gewählt werden?
Ja, nur wenige der mitgelieferten LayoutManager berücksichtigen die max size. Die Frage ist: wie soll das Layout denn am Ende aussehen? Evtl. reicht es schon, panel4 nochmal in den Norden eines Panels mit BorderLayout zu packen.
 
Weil das BorderLayout im Norden/Süden nur in der Breite, nicht aber in der Höhe resized. Analog im Westen/Osten nur in der Höhe aber nicht in der Breite. Und im Zentrum in beide Richtungen.
 
Passende Stellenanzeigen aus deiner Region:

Neue Themen

Oben