preferred size abhängig von Fenstergröße berechnen

hupfdule

Top Contributor
Hallo,

ich möchte die preferredSize einer Komponente abhängig von der Fenstergröße berechnen, in der sich die Komponente befindet. Dazu habe ich getPreferredSize() überschrieben

Java:
    @Override
    public Dimension getPreferredSize(){
      final Dimension prefSize= super.getPreferredSize();

      //calculate new preferred size based on the current preferred size
      prefSize.setSize(this.getWidth(), this.getWidth() / PREF_RATIO);

      return prefSize;
    }

Wie zu sehen ist, beziehe ich mich hier einfach auf die aktuelle preferred size und berechne daraus die neue gewünschte (wichtig ist halt, dass das Seitenverhältnis korrekt bleibt). Bei langsamem manuellem Vergrößern/Verkleinern des Fensters klappt das auch halbwegs. Macht man das zu schnell oder benutzt gar Maximize/Unmaximze des Windowmanagers, dann klappts halt nicht mehr, da die preferredSize der Komponente abgefragt wird, bevor die Änderung der Fenstergröße stattfindet. Zu dem Zeitpunkt kenn ich natürlich nur die alte Größe.

Was gibt es denn für sinnvolle Wege, mein Ziel zu erreichen, dass ich die preferredSize immer abhängig von der endgültigen Fenstergröße mache?
 
Zuletzt bearbeitet:

Guybrush Threepwood

Top Contributor
Sollte das nicht eher ein LayoutManager übernehmen? Z. B. FormLayout hat Möglichkeiten, die Größe dynamisch zu verändern und gleichzeitig auch minimale oder maximale Größem mit anzugeben.
 

hupfdule

Top Contributor
Es geht mir ja eben nicht um minimale und maximale Größen, sondern um das Seitenverhältnis der Komponente (was wiederum abhängig von deren Inhalt ist). Der LayoutManager kann es nicht wissen, er soll sich auf die preferredSize der Komponente beziehen. Und diese will ich ja verändern.
 

Marco13

Top Contributor
Ja, das Problem ist wohl (wie du schon angedeutet hast) dass die PreferredSize erst dann richtig berechnet werden kann, wenn sie schon berechnet wurde - das Layout "hinkt immer einen Größenänderungsschritt hinterher". Das merkt man teilweise auch bei anderen LayoutManagern (auch den schon vorhandenen, FlowLayout z.B.)
Du solltest ggf. trotzdem mal überlegen, ob das nicht mit einem LayoutManager gemacht werden kann: Ich hatte mal ein "AspectLayout" zusammengehackt ( http://www.java-forum.org/awt-swing-swt/89781-maximale-quadratische-groesse.html#post568106 ), was sich erstmal nur auf EINE Component bezieht. Wenn das für mehrere funktionieren soll, wird's natürlich schwierig (bis "unmöglich", d.h. man muss ggf. Kompromisse finden), aber vielleicht kann man ja das "Aspect Ratio" und ggf. irgendwelche "weights" (für die Kompromisse) in den Layout-Constraints unterbringen - sofern es nicht schon einen RICHTIGEN LayoutManager gibt, der das alles kann (es gibt so viele, ich hab' da nicht so den Überblick - mehr als Box, Border und Grid braucht man ja kaum ;) )
 

Guybrush Threepwood

Top Contributor
Noch so ein Gedanke: Die Komponenten kriegen ja einen Resize-Event. Diesen könnte man abfangen und die Preferred-Size auf die kleinere Seitenlänge setzen:

Java:
    public void componentResized(ComponentEvent e) {
        //hier die entsprechende Logik einbauen.            
    }

Könnte aber auch sein, dass das immer wieder aufgerufen wird und hängt.
 

Marco13

Top Contributor
Falls ich das richtig verstanden habe, geht es nicht um relative Größen zu anderen Components, sondern wirklich NUR um das Seitenverhältnis EINER Component.
 

Momolin

Aktives Mitglied
Hallo,

die Componente sollte ihre Container "kennen", wenn sie ihre preferredSize in Abhängigkeit von ihrem Container setzen soll:
Java:
import java.awt.Color;
import java.awt.Dimension;

import javax.swing.JComponent;
import javax.swing.JPanel;

public class RatioComponent extends JPanel {

	private double PREF_RATIO = 4.0 / 3.0;
	private JComponent container;

	// hier lernt sie ihren Container kennen
	public RatioComponent(JComponent container) {
		// dass man was sieht :-)
		this.setBackground(Color.MAGENTA);
		this.container = container;
	}

	@Override
	public Dimension getPreferredSize() {
		Dimension result;

		// nur zur Sicherheit oder für GUI-Builder
		if (container != null) {
			if (container.getWidth() > container.getHeight()) {
				result =
						new Dimension(container.getHeight(),
								(int) (container.getHeight() / PREF_RATIO));
			}
			else {
				result =
						new Dimension(container.getWidth(),
								(int) (container.getWidth() / PREF_RATIO));
			}
		}
		else
			result = new Dimension(300, 200);
		return result;
	}
}

Grüße
Momolin
 

hupfdule

Top Contributor
Falls ich das richtig verstanden habe, geht es nicht um relative Größen zu anderen Components, sondern wirklich NUR um das Seitenverhältnis EINER Component.

Korrekt, daher wird mir ein vorgefertigter LayoutManager da nicht helfen.


Du solltest ggf. trotzdem mal überlegen, ob das nicht mit einem LayoutManager gemacht werden kann: Ich hatte mal ein "AspectLayout" zusammengehackt (http://www.java-forum.org/awt-swing-swt/89781-maximale-quadratische-groesse.html#post568106), was sich erstmal nur auf EINE Component bezieht.

Das fänd ich eigentlich etwas viel für meinen Zweck, scheint aber ein guter Ansatzpunkt zu sein. Sollte ich mal überlegen, ob ich das nutze.

Noch so ein Gedanke: Die Komponenten kriegen ja einen Resize-Event. Diesen könnte man abfangen und die Preferred-Size auf die kleinere Seitenlänge setzen:

Stimmt. Daran hatte ich nicht gedacht. So funktioniert es auch. Und es ergibt keine Endlosschleife. :)
Da das so gut funktioniert, werde ich diesen Weg dem eigenen LayoutManager vorziehen.

Vielen Dank euch beiden!
 

Momolin

Aktives Mitglied
Hallo,

Stimmt. Daran hatte ich nicht gedacht. So funktioniert es auch. Und es ergibt keine Endlosschleife. :)
Da das so gut funktioniert, werde ich diesen Weg dem eigenen LayoutManager vorziehen.
Vielen Dank euch beiden!

es gibt zwar keine Endlosschleife, aber sehr schnell eine winzige Componente. Mit jedem "kleiner machen der Dimension" löst man ja das ResizeEvent aus und macht dann die Componente wieder kleiner - solange bis sie nicht mehr da ist.
 

hupfdule

Top Contributor
es gibt zwar keine Endlosschleife, aber sehr schnell eine winzige Componente. Mit jedem "kleiner machen der Dimension" löst man ja das ResizeEvent aus und macht dann die Componente wieder kleiner - solange bis sie nicht mehr da ist.

Nein, passiert nicht. Ich wüsste auch gar nicht wieso. Das Problem wäre höchstens, wenn das Setzen der Dimension wiederum einen resize-Event auslösen würde, was offensichtlich nicht der Fall ist.

So habe ich jetzt umgesetzt:
Java:
    this.addComponentListener(new ComponentAdapter() {
          @Override
          public void componentResized(ComponentEvent e) {
              final Dimension d= getPreferredSize();
              setSize(d);
              revalidate();            
          }
        });

    @Override
    public Dimension getPreferredSize(){
      final Dimension prefSize= super.getPreferredSize();
 
      //calculate new preferred size based on the current preferred size
      prefSize.setSize(this.getWidth(), this.getWidth() / PREF_RATIO);
 
      return prefSize;
    }

Zu deiner Idee mit der RatioComponent: Ich habe es nicht ausprobiert, aber mir scheint das genau das selbe Problem zu sein, wie bei der Lösung in meinem ersten Post (also ohne das resize-Event zu beachten). Ich bin immer eine Größenänderung hinterher.
 

Marco13

Top Contributor
Naja, es ist ewas hakelig, man müßte sich da schon nochmal SEHR genau Gedanken drüber machen, aber... Durch das 'validate' wird das Layout neu angestoßen. Dadurch händert sich vielleicht (vielleicht auch nicht) die Größe der Component. Dadurch wird die PreferredSize geändert und das validate aufgerufen...
Da kann schon was schiefgehen. Ich hatte, als das vorgeschlagen wurde, auch gleich irgendwelche "Race Conditions" im Hinterkopf, GANZ grob: Dass er irgendein Aspect-Ratio hat, durch das er die Component 100 Pixel breit macht, dann die oben angedeutete Kette durchläuft und dabei die Component 99 Pixel breit macht, dann wieder die Kette durchläuft und sie wieder 100 breit macht.......
Es KANN sein, dass dieser Fall (bei dir, oder allgemein) nicht auftreten kann, aber das sollte man wirklich genau durchdenken...
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
L JavaFX Canvas max size? AWT, Swing, JavaFX & SWT 1
P JFrame Location-/Size-Probleme AWT, Swing, JavaFX & SWT 5
F GWT Screen size AWT, Swing, JavaFX & SWT 2
M Font Size in FormsEditor AWT, Swing, JavaFX & SWT 2
N Richtiges einstellen der size von JPanels AWT, Swing, JavaFX & SWT 10
S jTable size und Text darstellung AWT, Swing, JavaFX & SWT 2
1 Swing manual resize table column to min size AWT, Swing, JavaFX & SWT 2
E Jlable text an size scalieren AWT, Swing, JavaFX & SWT 6
G JOptionPane.showConfirmDialog size problem AWT, Swing, JavaFX & SWT 3
A Swing Frame-Size / JButton AWT, Swing, JavaFX & SWT 19
Dragonfire Swing CardLayout Maximum Size AWT, Swing, JavaFX & SWT 7
B SWT Problem mit Alignment/Size AWT, Swing, JavaFX & SWT 3
R Container Size Problem AWT, Swing, JavaFX & SWT 5
S JPanel ohne Size AWT, Swing, JavaFX & SWT 7
F JComboBox Size AWT, Swing, JavaFX & SWT 2
E Problem mit JPanel - Wann wird size berechnet? AWT, Swing, JavaFX & SWT 5
G JPanel immer max-size öffnen. Wie? AWT, Swing, JavaFX & SWT 9
O JFrame und Size der Komponenten AWT, Swing, JavaFX & SWT 3
A checkbox in einer TableView abhängig von einem anderen Celleninhalt disablen AWT, Swing, JavaFX & SWT 1
C Swing Anzeigeproblem mit TableModels abhängig von deren Inhalt AWT, Swing, JavaFX & SWT 10
A JProgressBar updaten abhängig vom Output eines externen Skripts AWT, Swing, JavaFX & SWT 2
U JTable: Zeilen abhängig vom Datensatz einfärben AWT, Swing, JavaFX & SWT 4
R JTable Hintergrund der Zeile abhängig von Inhalt einer Zelle verändern AWT, Swing, JavaFX & SWT 3
A Flexible JTable mit editierbaren Zellen,abhängig von Data AWT, Swing, JavaFX & SWT 2
P seltsame Performance Probleme bei 2 Guis abhängig vom Aufruf AWT, Swing, JavaFX & SWT 8
P Zeichen abhängig davon, ob sich eine Variable geändert hat AWT, Swing, JavaFX & SWT 2
H Screenshot abhängig von Grafikkarte? AWT, Swing, JavaFX & SWT 15
G Button abhängig von aktiviertem tab anzeigen ? AWT, Swing, JavaFX & SWT 8
T Pixel OS abhängig AWT, Swing, JavaFX & SWT 3
R "\t" LnF abhängig !? - Ändern? AWT, Swing, JavaFX & SWT 7

Ähnliche Java Themen


Oben