PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Panelgröße Dynamisch ändern


ethrandil
2003-12-14, 21:21:43
Hi,
ich habe eine Anwendung, die auf höchster Ebene ein BorderLayout benutzt.
In der Region 'NORTH' ist nun ein JPanel mit ca 7 Buttons, welche nebeneinander dargestellt werden.

Wenn ich nun aber das Fenster verkleinere, dann rutschen die hinteren Buttons in die 2. Reihe. Der Ausschnitt für 'NORTH' wird aber nicht vergrößert!
D.H. die letzteren Buttons sind nicht mehr sichtbar!

Wie kann ich dieses Verhalten ändern? (Wenn möglichh ohne vom BorderLayout wegzukommen)

Eth

AHF
2003-12-14, 22:15:14
aus der api zu BorderLayout:

The components are laid out according to their preferred sizes and the constraints of the container's size. The NORTH and SOUTH components may be stretched horizontally; the EAST and WEST components may be stretched vertically; the CENTER component may stretch both horizontally and vertically to fill any space left over.

möglich wäre, eine minimum size für den container anzugeben, der ein verkleinern verhindert...oder ein JScrollPane verwenden und das JPanel reinsetzen. mehr fällt mir momentan dazu nicht ein.

HellHorse
2003-12-15, 18:35:38
Welches Laout verwendet denn das JPanel, der die Buttons enthält? Flow?
Und nachher sollten die Buttons in mehreren Reihen sein?
Da müsste eigentlich die prefered size vom JPanel angepasst werden. Schau doch mal nach, ob das geschieht.

Minimum size zu ändern halte ich für unnötig, da ja steht, dass auf die prefered size geachtet wird.

AHF
2003-12-15, 22:03:49
minimum size bezog sich auf den container mit dem borderlayout, ansonsten eben preferred size.
wobei ich eben nicht sicher bin, ob sich dieser wert auch auf das verkleinern des containers bezieht, sondern eben nur das verhältnis center-north (bzw. die anderen 'richtungen') festlegt.

HellHorse
2003-12-16, 19:35:28
Minimum Size für das content pane zu setzten bringt nichts.
siehe:
http://www.forum-3dcenter.org/vbulletin/showthread.php?s=&threadid=108493
aber das solltet ihr beide eigentlich wissen ;)
So wie ich das verstanden habe, respektiert BorderLayout prefered size von allen fünf Komponenten.
NORTH und SOUTH werden horizontal gestreckt, WEST und EAST vertikal und CENTER in beide Richtungen.
(steht ja so im Zitat)
Zudem sollten wir im gegebenen Fall ja nicht premanent unter prefered size fallen.
Bei JPanel kommt es ja wie von ethrandil beschrieben vor, aber dann müsste sie ja neu brechnet werden (weniger breit aber höher), so dass das Layout vom content pane geändert wird (CENTER wird gequetscht).

AHF
2003-12-16, 21:21:37
ich weiß nicht, was ethrandil als top-level container verwendet, aber bei einem jframe gibt es die setMinimumSize(dimension) ja nicht. in dem geposteten link auf meinem thread steht ja auch die antwort, wie man eine minimumsize erzwingt.

ich habe eben mal ein JPanel getestet und muss feststellen, dass weder setMinimumSize(dimension), setSize(dimension) noch setMaximumSize(dimension) irgendetwas bewirken. wozu gibt es diese methoden eigentlich? oder muss man davor noch etwas auf true setzen?

edit: habe gerade gelesen, boxlayout hält sich an diese größen.

So wie ich das verstanden habe, respektiert BorderLayout prefered size von allen fünf Komponenten.
NORTH und SOUTH werden horizontal gestreckt, WEST und EAST vertikal und CENTER in beide Richtungen.
(steht ja so im Zitat)

so ist es auch: bei north und south werden die vertikale komponente und bei east und west die horizontale komponente der preferred size beachtet. bei center hat es keinen sinn, eine zu setzen.
beim verkleinern wird center auch als erstes komplett 'verspeist', danach gehts an die restlichen komponenten. setzt man keine preferred size gilt die summe der größe der komponenten.

HellHorse
2003-12-17, 15:20:43
Die ist eine Idee, wie eine mögliche Lösung aussehen könnte

public class LayoutFrame extends JFrame {
public LayoutFrame() {
super();
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
this.initLayout();
this.setSize(400, 200);
}

private void initLayout() {
Container contentPane = this.getContentPane();
contentPane.setLayout(new BorderLayout());
contentPane.add(new JButton("WEST"), BorderLayout.WEST);
contentPane.add(new JButton("EAST"), BorderLayout.EAST);
contentPane.add(new JButton("CENTER"), BorderLayout.CENTER);
contentPane.add(new JButton("SOUTH"), BorderLayout.SOUTH);
contentPane.add(this.makeNorthComponent(), BorderLayout.NORTH);
}

private Component makeNorthComponent() {
JPanel northPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
northPanel.add(new JButton("eins"));
northPanel.add(new JButton("zwei"));
northPanel.add(new JButton("drei"));
northPanel.add(new JButton("vier"));
northPanel.add(new JButton("fünf"));
northPanel.addComponentListener(new SomeComponentListener());
return northPanel;
}

public static void main(String[] args) {
Frame frame = new LayoutFrame();
frame.setVisible(true);
}

private class SomeComponentListener extends ComponentAdapter {
public void componentResized(ComponentEvent componentEvent) {
// wer hätte gern generics ;)
JComponent component = (JComponent) componentEvent.getComponent();
if (component.getWidth() < component.getPreferredSize().getWidth()) {
// nur schnell hingepfuscht, hier müsste man besser rechnen
component.setPreferredSize(new Dimension(component.getWidth(), component.getHeight() * 2));
}
}
}
}

Natürlich darf man nicht einfach vergrössern, das ist nur schnell hingepfuscht um zu sehen, ob es läuft.
Man müsste über alle Komponenten iterieren und auch die Abstände dazwischen beachten.
Es müsste auch die originale prefered size gespeichert werden, und immer versucht werden sie wiederherzustellen.
Aber es funktioniert einigermassen bei mir.

ethrandil
2003-12-17, 16:41:31
Das war ein guter Tipp, danke.

Ich habe es nun so:

buttonPanel.addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent componentEvent) {
JComponent component = (JComponent) componentEvent.getComponent();

FlowLayout l = (FlowLayout) component.getLayout();
Component[] comps = component.getComponents();
int maxheight = 0, //Temp-maximum für jede reihe
height = l.getHgap(),//Gesamthöhe
width = l.getVgap();//Spaltenbreite

//Schleife über jede 'Mitglied-Component'
for(int i=0; i < comps.length; ++i){
Dimension size = comps[i].getPreferredSize();

//wenn die aktuelle Component die Spalte überschreitet
if(width + size.width + l.getVgap() > component.getWidth()){
//dann addiere die bisherige Maximalhöhe zur Gesamthöhe
height += maxheight + l.getHgap();
maxheight = size.height;
width = size.width + l.getVgap();
}else{
//ansonsten zähle die Componentbreite zur Spaltenbreite
width += size.width+l.getVgap();
//und aktualisiere ggf die Maximalhöhe
if(size.height > maxheight)
maxheight = size.height;
}
}
//Für die letzte Spalte, die ja noch nicht beendet ist
height += maxheight;

component.setPreferredSize(new Dimension(component.getWidth(), height));

//Aktualisieren
component.getParent().validate();
component.getParent().doLayout();
}
});


So, jetzt gehts.
Danke für den Hinweis!

EDIT: Kommentarrechtschreibung :freak: