Swing maximale quadratische Größe

Status
Nicht offen für weitere Antworten.

banshee

Bekanntes Mitglied
Hallo,

wenn ich eine Komponente in ein GridbagLayout eingeflechted habe, wie kann ich es erreichen, dass sie immer quadratisch, aber eben maximale Größe auf dem Anzeigebereich hat? Einfach mit setPreferredSize einen fixen Wert einzutragen bringt da ja nichts, weil es auf Monitoren anderer Größe dann wieder komplett anders aussieht.
Meine theoretische Lösung wäre ja folgende: Komponente erstellen, Defaultsize berechnen lassen, an der längeren Achse so verkleinern, dass sie quadratisch ist. Allerdings scheint das berechnen der Defaultsize ja einer der letzten Schritte vor dem Anzeigen zu sein (auch wenn ich mich mit den internen Mechanismen jetzt nicht 100%ig auskenne)
 

Marco13

Top Contributor
Hm ... ich hatte mal ein AspectLayout geschrieben, das eine einzelne Component mit einem bestimmten Seitenverhältnis (bei dir: 1.0) anzeigt - kann ich mal posten, wenn ich wieder am ensprechenden Rechner sitze...
 

banshee

Bekanntes Mitglied
ja, das wäre prima. Ich hab mir die JGoodies Forms mal angeschaut und finde das auch für die Zukunft sehr interessant, aber das jetzt noch irgendwie in das Projekt zu quetschen, obwohl der Rest schon mit anderen Layout-Managern gemacht ist, sieht dann am Ende auch nicht schön aus.
Außerdem hab ich es bis jetzt noch nicht raus, wie ich da eine Komponente quadratisch mache. Muss ich die columns dann in dlu so festlegen, dass sie quadratisch sind und die Komponente immer mitstauchen?

Ich habe hier mal einen screenshot von dem Panel gemacht, wo ich das brauche:



Hier sollten also das große Panel oben links und die 8 kleinen unten immer quadratisch sein. Ich sehe hier vor allen Dingen einen Konflikt mit dem rowspan aufkommen. Wenn ich nämlich einstelle, dass das obere Panel über den 7 kleinen liegt, wird es doch automatisch immer verlängert, auch wenn es schon nach 5 aufhören müsste, um quadratisch zu bleiben?!
 

Marco13

Top Contributor
Aufgrund seiner Trivialität hiermit ins public domain entlassen:

Java:
import java.awt.*;

/**
 * An implementation of the LayoutManager interface, for containers
 * that contain a single component that should be as large as 
 * possible under the constraint that a given aspect ratio 
 * (width/height) is maintained.
 */
public class AspectLayout implements LayoutManager
{
    /**
     * The current aspect that should be maintained
     */
    private float aspect = 1.0f;
    
    /**
     * The alignment in horizontal or vertical direction.
     * If there is extra space in either direction, then
     * the component will aligned according to this value
     */
    private float alignment = 0.5f;
    
    /**
     * Creates a new AspectLayout for the given aspect
     * 
     * @param aspect The aspect for the contained component
     */
    public AspectLayout(float aspect)
    {
        this.aspect = aspect;
    }

    /**
     * Creates a new AspectLayout for the given aspect and
     * alignment
     * 
     * @param aspect The aspect for the contained component
     * @param alignment The alignment for the contained component
     */
    public AspectLayout(float aspect, float alignment)
    {
        this.aspect = aspect;
        this.alignment = alignment;
    }
    
    /**
     * {@inheritDoc}
     */
    public void addLayoutComponent(String name, Component comp)
    {
    }

    /**
     * {@inheritDoc}
     */
    public void layoutContainer(Container parent)
    {
        synchronized (parent.getTreeLock()) 
        {
            if (parent.getComponentCount() == 0)
            {
                return;
            }
            Insets insets = parent.getInsets();
            int maxWidth = parent.getWidth() - (insets.left + insets.right);
            int maxHeight = parent.getHeight() - (insets.top + insets.bottom);
            
            int maxAspectW = (int)(maxHeight * aspect);
            int maxAspectH = (int)(maxWidth / aspect);
            
            //System.out.println("maxAspectW "+maxAspectW+" "+maxAspectH+" maxAspectH"); 
            
            Component component = parent.getComponent(0);
            
            if (maxAspectW > maxWidth)
            {
                int w = maxWidth;
                int h = maxAspectH;
                int space = maxHeight - h;
                int offset = (int)(alignment * space);
                component.setBounds(insets.left, insets.top + offset, w, h);
            }
            else
            {
                int w = maxAspectW;
                int h = maxHeight;
                int space = maxWidth - w;
                int offset = (int)(alignment * space);
                component.setBounds(insets.left+offset, insets.top, w, h);
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    public Dimension minimumLayoutSize(Container parent)
    {
        if (parent.getComponentCount() == 0)
        {
            return new Dimension(0,0);
        }
        Component component = parent.getComponent(0);
        return component.getMinimumSize();
    }

    /**
     * {@inheritDoc}
     */
    public Dimension preferredLayoutSize(Container parent)
    {
        if (parent.getComponentCount() == 0)
        {
            return new Dimension(0,0);
        }
        Component component = parent.getComponent(0);
        return component.getPreferredSize();
    }

    /**
     * {@inheritDoc}
     */
    public void removeLayoutComponent(Component comp)
    {
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() 
    {
        return getClass().getName() + "[aspect=" + aspect + "]";
    }
    
    /*/
    public static void main(String args[])
    {
        javax.swing.JFrame f = new javax.swing.JFrame();
        f.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
        f.getContentPane().setLayout(new AspectLayout(2.0f));
        javax.swing.JPanel p = new javax.swing.JPanel()
        {
            public void paintComponent(Graphics g)
            {
                super.paintComponent(g);
                g.setColor(Color.BLACK);
                g.drawString(""+getSize(), 10, 20);
            }
        };
        p.setPreferredSize(new Dimension(700,200));
        p.setBackground(Color.RED);
        f.getContentPane().add(p);
        f.pack();
        f.setVisible(true);
    }
    //*/
    
}
 

Marco13

Top Contributor
Noch als Nachtrag: Ich hatte das verwendet, um ein Spielfeld mit einem bestimmten Seitenverhältnis darzustellen. Bei dir wäre dann im oberen linken Panel das AspectLayout, und IN dem Panel dann der eigentliche Inhalt, der immer Quadratisch sein soll. Dass das bei der Anforderung, dass bestimmte Comonents immer Quadratisch sein sollen, zu Widersrpüchen kommen kann, ist klar, deswegen legt das AspectLayout immer nur EINE Component in ein (ansonsten leeres) Panel, und läßt ggf. links&rechts bzw. oben&unten ein bißchen Platz...
 

banshee

Bekanntes Mitglied
Vielen Dank, funktioniert super. Ich habe allerdings das Gefühl, dass mir Swing einfach den nächst größeren Stein in die Bahn wirft, sobald ein Problem gelöst ist. Schaut euch zu folgendem unbedingt nochmal den Screenshot an.

Ich zeichne also eine Matrix mit Java2D oben links. Wenn es gut läuft, passt sie genau ins Fenster und alle sind glücklich. Wenn es schlecht läuft, ist die Matrix allerdings so riesig, dass nur ein Teil ins Bild passt und der Rest per Scrollbalken angezeigt wird.
Das wird zum Problem, wenn ich danach eine Matrix lade, die normalerweise wieder ins Bild passen würde. Ich schaue mir nämlich zuerst die Initialwerte des Panels an, versuche die Matrix dann erst so zu zeichnen, dass sie genau reinpasst und schalte eben die Scrollbalken ein, falls die Größe einer Zeller kleiner als x Pixel ist. Wenn ich die Größe dann durch eine Riesenmatrix aber verändert habe, zeichnet er auch z.B. eine 3x3 Matrix in dieses Riesenpanel mit den Scrollbalken. Ich bräuchte also einen Befehl, der das JPanel in seinen Ursprungszustand zurückversetzt, damit ich die wirklichen Initialwerte (= als das Panel noch komplett leer war) bekomme. Gibt es sowas?
 

Marco13

Top Contributor
???:L Häh? Man kann z.B. bei einer Scollbar die "policy" setzen, wann Scrollbalken angezeugt werden... ?! Poste notfalls mal ein Stück code...
 

banshee

Bekanntes Mitglied
Ja ich benutze einfach das Std-Dingens mit VERT/HORZ_AS_NEEDED. Aber folgendermaßen:

Java:
private void initPaint() {
		double minLen = (getWidth() < getHeight()) ? getWidth() : getHeight();
		rectSize = (float)minLen / colCount;

		if(rectSize < 10.0f)
			rectSize = 10.0f;

		Font font = new Font("Dialog", Font.PLAIN, 10);
		setFont(font);
	}

Das ist der Code, der immer dann ausgeführt wird, wenn man eine neue Matrix zeichnet. Zeichne ich also eine Riesenmatrix, wird die Größe des JPanels verändert und wenn ich die Funktion oben das nächste mal aufrufe, rechnet sie eben mit der veränderten Größe weiter und er zeichnet auch kleine Matrizen in das Riesenpanel, was zur Folge hat, dass die Zellen riesig sind und trotzdem nur ein Teil sichtbar ist, obwohl die Matrix ganz in das Panel passen würde. Ich könnte natürlich einfach die Größe der ScrollPane abfragen, nur von der weiß das Panel, in dem die obere Funktion ist, nichts.

Was ich übrigens auch festgestellt hab: Wenn die Matrix zu groß ist, verändere ich die Panelgröße einfach mit setPreferredSize(). Er zeigt dann auch Scrollbalken an, verschiebt aber trotzdem jedesmal das gesamte Layout.

Erstellt wird das ganze einfach so:

Java:
JScrollPane scrollPane = new JScrollPane(bigPanel);
				
		layout.setConstraints(scrollPane, new GridBagConstraints(0, 0, 7, 1, 1, 4,
				GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0,
				0));

Und wenn ich das große Panel einfach direkt mal auf 600x600 setze, schiebt er die restlichen Komponenten einfach weg, obwohl die ScrollPane einfach Balken anzeigen sollte, anstatt ihre Größe zu ändern. Wie verhindere ich das?

 

Marco13

Top Contributor
Zusammengefasst würde das jetzt etwa lauten: Wenn ich etwas mache und dann noch etwas ist das Layout nicht so, wie ich es will.

Ein KSKB würde evtl. wirklich helfen...
 

banshee

Bekanntes Mitglied
Das hätte ich auch schon längst gemacht. Das Problem ist zum einen nur, dass es in dem KSKB komischerweise so funktioniert, wie ich das will und für das andere Beispiel lässt sich das nicht so einfach machen, weil die Klasse sehr viele andere Komponenten benutzt.
Mal sehen, ob ich nachher noch was basteln kann...
 

banshee

Bekanntes Mitglied
Für das erste Problem ging es eigentlich doch recht einfach

Java:
package test;

import javax.swing.*;

import java.awt.*;

public class Test extends JPanel {
	private static final long	serialVersionUID	= 1L;
	private static final int	PANEL_COUNT			= 8;
	private JPanel				bigPanel			= new JPanel();
	private final JPanel[]		previewPanels		= new JPanel[PANEL_COUNT];

	public Test() {
		for(int i = 0; i < PANEL_COUNT; i++)
			previewPanels[i] = new JPanel();

		setLayout(new BorderLayout());

		JPanel left = createLeftSection();
		add(left, BorderLayout.CENTER);
	}

	private JPanel createLeftSection() {
		JPanel leftSec = new JPanel();
		GridBagLayout layout = new GridBagLayout();
		leftSec.setLayout(layout);

		JScrollPane scrollPane = new JScrollPane(bigPanel);

		layout.setConstraints(scrollPane, new GridBagConstraints(0, 0, 7, 1, 1, 4,
				GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0,
				0));
		JPanel referenceBar = new JPanel();
		layout.setConstraints(referenceBar, new GridBagConstraints(7, 0, 1, 1, 1, 4,
				GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0,
				0));
		leftSec.add(scrollPane);
		leftSec.add(referenceBar);

		for(int i = 0; i < PANEL_COUNT; i++) {
			layout.setConstraints(previewPanels[i], new GridBagConstraints(i, 1, 1, 1, 1, 1,
					GridBagConstraints.CENTER, GridBagConstraints.BOTH,
					new Insets(0, 0, 0, 0), 0, 0));
			leftSec.add(previewPanels[i]);
			previewPanels[i].setBorder(BorderFactory.createLineBorder(Color.black));
		}

		//bigPanel.setPreferredSize(new Dimension(600, 600));

		return leftSec;
	}

	public static void main(String[] args) {
		JFrame frame = new JFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setExtendedState(Frame.MAXIMIZED_BOTH);
		frame.add(new Test());
		frame.setVisible(true);
	}
}

Wenn man den Code, so wie er ist, startet, sieht man das Fenster also, wie es eigentlich immer aussehen soll. Wenn man dann die auskommentierte Zeile reinmacht, quetscht er die unteren Panels, obwohl das bigPanel in eine JScrollPane eingebettet ist, die für den Fall - das bigPanel wird größer als sein Anzeigebereich - mit Scrollbalken einspringen sollte. Es scheint also, also ob die ScrollPane ihre Größe aus irgendwelchen Gründen mitändert. Sie soll aber immer die Initialgröße beibehalten.
 

Marco13

Top Contributor
Hm sorry - vielleicht hat jemand anderes Lust, sich durch GridBagConstraints zu wühlen und dir dein Wunschlayout zusammenzustellen.
 

banshee

Bekanntes Mitglied
Höre ich da etwa Kritik an meinem Codestil oder kannst du den Manager nicht leiden? :D

Ich dachte, das ist immernoch der beste der Std-Manager. Ich kann mir auch nicht wirklich vorstellen, dass es am layout liegt. Das ist ja zumindest initial so, wie ich es haben will. Die ScrollPane macht eben nur, was sie will.

Oder hätte ich das kommentieren sollen? Ich dachte mit Ergebnisscreenshot und Javadoc ist das recht leicht zu lesen. Ich weiß nämlich nicht, was ich da noch aufschreiben soll, was man nicht sowieso schon mit einem Blick auf den Code erkennt (zumindest wenn man den Manager schonmal benutzt hat)
 

banshee

Bekanntes Mitglied
okay, nochmal von vorne. Dass ich Matrizen zeichnen will, ist mittlerweile hoffentlich klar :D
Die Hauptmatrix wird in dem großen Panel gezeichnet und kleinere Vorschaumatrizen in den kleinen Panels unten. Die Hauptmatrix versucht dabei immer zuerst sich in den zur Verfügung stehenden Platz zu zeichnen. Jetzt kann es aber vorkommen, dass eine Matrix zu groß ist (z.B. wenn man eine 1000x1000 Matrix in das 600x600 Panel zu zeichnen versucht). Dann soll sich aber trotzdem nichts am Layout ändern, sondern man soll die Matrix scrollen können.

In dem Codestück habe ich also einfach mal simuliert, dass eine große Matrix angezeigt wird, indem ich das Panel, dass die ScrollPane "betrachtet" vergrößert habe und anstatt darauf mit Scrollbalken zu reagieren, wird das Layout gequetscht.

Wahrscheinlich liegt das am GridBagLayout. Ich hab aber keine Ahnung, wie ich so ein Layout ohne Manager hinbekommen soll, vor allem wenn es sich auf verschiedene Monitorgrößen anpassen soll, etc.
 

Michael...

Top Contributor
Da Dein Layout nach relativ komplexen Regeln aufgebaut ist, die mir noch nicht ganz klar sind (z.B. die acht quadratischen Panels: ist der relative/absolute Anteil an der Höhe begrenzt?) wurde ich empfehlen einen eigenen LayoutManager zu schreiben.

Sowohl für den eigenen als auch fertige LayoutManager gilt aber:
Die Regeln wie die Komponenten auf der Fläche verteilt werden sollen müssen eindeutig sein.
 

Marco13

Top Contributor
Was spricht dagegen, die Vorschaupanels in ein Panel mit GridLayout(1,8) zu legen, dieses Panel dann ins Hauptpanel in BorderLayout.SOUTH, und die eigentliche Matrix dann ins Hauptpanel mit BorderLayout.CENTER?
 

banshee

Bekanntes Mitglied
Gleiches Problem.

Ich versteh das gar nicht, dass diese ganzen Constraints so schwer zu verstehen sind. Ich sehe mittlerweile schon ein Layout vor mir, wenn ich den Code sehe und ich dachte, ich bin hier die Gurke :D

Im Prinzip sind ja nur die ersten 6 Zahlen in den Constraints interessant. Die ersten beiden geben die x/y-Koordinaten an, d.h. das große Panel logischerweise (0, 0), die referenceBar (da das große Panel horizontal 7 Vorschau-Panels überspannt) erst wieder bei (7, 0) und die Vorschau-Panels eben bei (i, 1), i = 1..8.
Die nächsten beiden Zahlen geben den span an. Der ist überall 1 außer, wie schon beschrieben, beim großen Panel.
Hinten dann die Gewichtung, wie freier Platz aufgeteilt wird. Die oberen Komponenten (großes Panel und referenceBar) sollen vertikal ein 4:1 Verhältnis zu den Vorschaupanels haben und auf der x-Achse gilt für alle der Standard.

Das BorderLayout aus dem Konstruktor kann man eigentlich getrost ignorieren. Das hab ich nur eingefügt, damit die leftSection über den gesamten JFrame geht.
 

banshee

Bekanntes Mitglied
Nochmal eine etwas andere Sache:

Designtechnisch ist es ja garantiert besser, wenn man die Berechnungen und das eigentliche Zeichnen der Matrix trennt. Nur, um den Platz zu bestimmen, den die Beschriftung braucht, muss man ja über ein Graphics-Objekt auf die FontMetrics zugreifen. Ich kann mich allerdings erinnern, wie ich vor einiger Zeit irgendwo mal gelesen habe, dass man das Graphics-Objekt auf keinen Fall außerhalb der paintComponent mit getGraphics() abfragen sollte (die Begründung dazu weiß ich nicht mehr bzw. die gab es auch gar nicht). Es macht ja auch irgendwo Sinn, denn woher soll ein Panel wissen, auf welchem Graphics-Context es mal gezeichnet wird.

Was macht man da?
 

Marco13

Top Contributor
Wenn mich nicht alles täuscht bekommt das Graphics den Font, der auf der Component gesetzt ist, die gezeichnet werden soll (also mal panel.getFont und panel.setFont anschauen)... kann mich aber auch irren. Hat sich das mit dem Layout erledigt?
 

banshee

Bekanntes Mitglied
Das Problem mit dem Layout hat sich nur teilweise erledigt. Ein revalidate() nach setPreferredSize() schaltet zumindest die Scrollbalken ein, wann ich will, aber jede Aktion, die irgendwie die View updated, zerschießt wieder alles.
 
Zuletzt bearbeitet:

banshee

Bekanntes Mitglied
Updates: Das mit getFont() hat sehr gut geklappt, vielen Dank schonmal dafür :)

Mit dem Layout bin ich auch nen Schritt weiter. Das Problem, dass sich das Layout beim Neuladen eines anderen Files zerschossen hat, lag an einem validate(), was ich anscheinend gar nicht brauchte.
Nur beim resizen macht er eben noch alles kaputt. Die Frage ist jetzt, was ich mache. Ich kann natürlich irgendwie das OnResize-Event so überschreiben, dass er darin kein validate aufruft, das sieht mir aber irgendwie nur nach Verlagerung des Problems aus...
Die Frage ist auch, ob ich damit alle Fälle abdecke. Gehört da denn auch sowas dazu wie einen SplitPaneSeparator zu verschieben?
 

Marco13

Top Contributor
Wie gesagt, ich weiß nicht, was gegen sowas spricht
Code:
import javax.swing.*;

import java.awt.*;

public class PanelLayoutTest extends JPanel {
    private static final long   serialVersionUID    = 1L;
    private static final int    PANEL_COUNT         = 8;
    private JPanel              bigPanel            = new JPanel();
    private final JPanel[]      previewPanels       = new JPanel[PANEL_COUNT];

    public PanelLayoutTest() {
        for(int i = 0; i < PANEL_COUNT; i++)
            previewPanels[i] = new JPanel();

        setLayout(new BorderLayout());

        JPanel left = createLeftSection();
        add(left, BorderLayout.CENTER);
    }

    private JPanel createLeftSection() {
        JPanel leftSec = new JPanel();
        leftSec.setLayout(new BorderLayout());

        JScrollPane scrollPane = new JScrollPane(bigPanel);
        JPanel previews = new JPanel(new GridLayout(1,PANEL_COUNT));
        JPanel thisOtherOne = new JPanel();
        thisOtherOne.setPreferredSize(new Dimension(300,300));

        leftSec.add(scrollPane, BorderLayout.CENTER);
        leftSec.add(previews, BorderLayout.SOUTH);
        leftSec.add(thisOtherOne, BorderLayout.EAST);

        for(int i = 0; i < PANEL_COUNT; i++) {
            previews.add(previewPanels[i]);
            previewPanels[i].setBorder(BorderFactory.createLineBorder(Color.black));
            previewPanels[i].setPreferredSize(new Dimension(300,300));
        }

        bigPanel.setPreferredSize(new Dimension(600, 600));

        return leftSec;
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setExtendedState(Frame.MAXIMIZED_BOTH);
        frame.add(new PanelLayoutTest());
        frame.setVisible(true);
    }
}

Aber wenn du das andere besser findest, und/oder weder klar sagst, wie groß die einzelnen Panels sein sollen oder welche Größenverhältnisse sie haben sollen, oder was wann passieren soll, wenn man es vergrößert oder verkleinert, kann ich dir nicht weiterhelfen.

Kannst ja von allen Components, die du erstellst, die "validate"-Methode überschreiben
Code:
panel = new JPanel()
{
    public void validate()
    {
        System.out.println("Nee, das mach' ich lieber selbst");
    }
};
(hier müßte jetzt irgendein Smiley hin)
 

banshee

Bekanntes Mitglied
Sorry konnte mich länger nicht darum kümmern, weil die Deadlines anderer Fächer näher waren ;)

Also um es mal kurz zu machen: Deinen Ansatz habe ich auch schon probiert und das Problem ist das gleiche. Mir geht es auch gar nicht um ein ganz besonderes Verhältnis des Layouts oder ähnliches, sondern um das hier:

Java:
package org.fvscale.ui.main;

import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class Test2 extends JPanel {
	private JFrame frame;
	
	Test2() {
		GridBagLayout layout = new GridBagLayout();
		setLayout(layout);
		
		JPanel a = new JPanel();
		JPanel b = new JPanel();
		JPanel c = new JPanel();
		JPanel d = new JPanel();
		JScrollPane sc = new JScrollPane(a);
		
		layout.setConstraints(sc, new GridBagConstraints(0, 0, 1, 1, 1, 1,
				GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0,
				0));
		layout.setConstraints(b, new GridBagConstraints(1, 0, 1, 1, 1, 1,
				GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0,
				0));
		layout.setConstraints(c, new GridBagConstraints(0, 1, 1, 1, 1, 1,
				GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0,
				0));
		layout.setConstraints(d, new GridBagConstraints(1, 1, 1, 1, 1, 1,
				GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0,
				0));
		
		add(sc);
		add(b);
		add(c);
		add(d);
		
		a.setPreferredSize(new Dimension(800, 800));
		a.revalidate();
	}
	/**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private static void createAndShowGUI() {
        //Create and set up the window.
        JFrame frame = new JFrame("ScrollDemo2");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Create and set up the content pane.
        JComponent newContentPane = new Test2();
        newContentPane.setOpaque(true); //content panes must be opaque
        frame.setContentPane(newContentPane);

        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

Ich erstelle hier einen Frame mit GridBagLayout, das 4 gleich große JPanels beinhalten soll. Das JPanel oben links ist zusätzlich noch in eine JScrollPane eingebettet. Was jetzt passiert, wenn ich die preferredSize des eingebetteten Panels erhöhe (und zusätzlich validate() aufrufe, was laut Dokumentation für eine Neuberechnung der ScrollPane reichen sollte), sprengt er mir das Layout. D.h. die Komponenten sind nicht mehr gleich groß, sondern die nun vergrößerte JScrollPane(!!!) drückt die anderen 3 Panels an den Rand.

Was ich will: Die größe der JScrollPane soll sich niemals durch eine Zeichenoperation auf dem darin liegenden Panel ändern, sondern sie soll ihre Größe beibehalten und Scrollbalken anzeigen, sobald das Panel zu größ wird. Oder kurz: Der JFrame soll jederzeit in 4 gleich große Bereiche unterteilt sein. Man kann ja z.B. mal die preferredSize eines der anderen 3 JPanels vergrößern. Darauf reagiert der JFrame mit einer gleichmäßigen Verteilung für alle 4 Komponenten. Warum?
 

Marco13

Top Contributor
Beim GridBagLayout :autsch: werden Gewichte angegeben. Die PreferredSize vom einen Panel ist 800,800, und die von den anderen ist 0,0. Was soll er machen?

Zwei Alternativen: GridLayout(2,2) verwenden, oder allen 4 Panels eine PreferredSize von 800,800 geben.

EDIT: Und eine dritte, ziemlich Hackig:
sc.setPreferredSize(new Dimension(0,0));

Und noch eine potentielle vierte: Das JPanel a könnte von einer Klasse sein, die Scrollable geeignet implementiert.
 

banshee

Bekanntes Mitglied
EDIT: Und eine dritte, ziemlich Hackig:
sc.setPreferredSize(new Dimension(0,0));

Ja, genau die hab ich gestern auch gefunden und war ziemlich glücklich :)

Eine (hoffentlich) letzte Frage noch: Kann man irgendwie die Initialgrößenberechnung von Swing vorziehen? Also z.B:

Java:
JFrame frame = new JFrame("foo");
		frame.getContentPane().setLayout(new BorderLayout());
		JScrollPane scrollPane = new JScrollPane(panel);
		frame.setSize(new Dimension(800, 800));
		frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
		panel.getVisibleRect() // = [0, 0]

Ich will also erneut die Zeichnerei perfekt auf die Anzeigegröße auslegen und müsste dazu wissen, wie groß das Panel später ist. Ich kann es natürlich mit 800x800 harcoden, aber das ist wohl ziemlich unelegant...
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
I JOptionPane maximale Zeichen einstellen AWT, Swing, JavaFX & SWT 2
E TextArea - Maximale Zeichenanzahl AWT, Swing, JavaFX & SWT 2
S Swing jFrame auf maximale Größe setzten AWT, Swing, JavaFX & SWT 7
G LayoutManager BorderLayout WEST Bereich auf maximale Größe beschränken AWT, Swing, JavaFX & SWT 19
T Maximale Länge eines JButtons AWT, Swing, JavaFX & SWT 5
S Swing Swing maximale Fenstergrösse ermitteln AWT, Swing, JavaFX & SWT 5
X Maximale Zeilenanzahl einer JTable erweitern AWT, Swing, JavaFX & SWT 7
G BufferedImage und jpg --> maximale Qualität AWT, Swing, JavaFX & SWT 9
M Komponenten auf maximale Größe zwingen AWT, Swing, JavaFX & SWT 2
G Maximale Größe JFrame AWT, Swing, JavaFX & SWT 2
D Maximale Anzahle der Zeilen in JTextArea AWT, Swing, JavaFX & SWT 5
P JTextField wird nur sehr klein angezeigt und verändert die Größe nicht AWT, Swing, JavaFX & SWT 3
H JDialog in Größe ändern - Resize-Cursor bleibt betreten der Komponente AWT, Swing, JavaFX & SWT 1
H AWT Dialog Größe ändern - Schwarzer Inhalt beim groß ziehen AWT, Swing, JavaFX & SWT 1
Yonnig JavaFX Größe von WebView an Content anpassen AWT, Swing, JavaFX & SWT 3
J Swing Komponente wird unpassend angepasst in der Größe AWT, Swing, JavaFX & SWT 35
FrittenFritze Ein Problem mit der CSSBox, die Größe wird nicht angepasst AWT, Swing, JavaFX & SWT 5
D JavaFX Größe des Bild an ImageView anpassen AWT, Swing, JavaFX & SWT 3
B Dynamische ListView-Größe, die bei Fenstergrößenänderung sich anpasst AWT, Swing, JavaFX & SWT 19
R Swing JTextField - Schriftgröße je nach Länge und Größe ändern AWT, Swing, JavaFX & SWT 0
B veränderte Größe eines Panels im Vorhinein wissen? AWT, Swing, JavaFX & SWT 1
B Größe der Parent-Component dynamisch an children anpassen AWT, Swing, JavaFX & SWT 30
L JavaFX AnchorPane an die Größe der Scene oder Window binden? AWT, Swing, JavaFX & SWT 3
K JavaFX Component Größe an Inhalt anpassen AWT, Swing, JavaFX & SWT 11
S Java GUI durch variable Größe einer Map anpassen AWT, Swing, JavaFX & SWT 3
R Größe von Scene und stage an grid anpassen AWT, Swing, JavaFX & SWT 4
M Java FX größe der shapes anpassen AWT, Swing, JavaFX & SWT 0
L Swing JPanel Größe anpassen AWT, Swing, JavaFX & SWT 6
E Wie kann ich ein JLabel auf größe der schriftlänge setzten? AWT, Swing, JavaFX & SWT 2
C Swing JFrame ändert Größe AWT, Swing, JavaFX & SWT 0
G Swing JButton ändert (unerwünscht) Größe bei Ausführung AWT, Swing, JavaFX & SWT 4
L Swing Größe automatisch anpassen AWT, Swing, JavaFX & SWT 14
B AWT Panel größe im BorderLayout einstellen AWT, Swing, JavaFX & SWT 1
J Swing Pane im SplitPane automatische Größe aktivieren AWT, Swing, JavaFX & SWT 0
DaCrazyJavaExpert Swing Größe des JPanel ändern/wird nicht geändert. AWT, Swing, JavaFX & SWT 3
M Swing Mehrere Textfelder mit ScrollBars - Größe der Felder AWT, Swing, JavaFX & SWT 0
L JavaFX ListView Größe anpassen AWT, Swing, JavaFX & SWT 1
Neumi5694 Größe von Komboboxen neu berechnen AWT, Swing, JavaFX & SWT 3
L JavaFX List oder TableView Größe dynamisch anpassen? AWT, Swing, JavaFX & SWT 4
P Größe und Ausrichtung von Komponenten festlegen AWT, Swing, JavaFX & SWT 13
I CSS - backgroundImage - Größe automatisch an den Container anpassen AWT, Swing, JavaFX & SWT 1
C Größe des Mauszeigers ermitteln AWT, Swing, JavaFX & SWT 5
MaxG. JFrame Größe ändern AWT, Swing, JavaFX & SWT 16
P Jframe Bild einfügen, Hintergrund Farbe ändern, und Button schrift Größe ändern AWT, Swing, JavaFX & SWT 2
K GridBagLayout verändert die größe? AWT, Swing, JavaFX & SWT 1
D Swing Größe einer JComboBox im GridBagLayout aufgrund der maximalen Länge der enthaltenen Daten AWT, Swing, JavaFX & SWT 7
D JavaFX Alle Knöpfe auf die gleiche Größe AWT, Swing, JavaFX & SWT 14
G JFrame - manuell Größe verändern AWT, Swing, JavaFX & SWT 6
M LayoutManager GridBagLayout passt seine größe nicht an AWT, Swing, JavaFX & SWT 3
F Gui weicht von Designpreview ab (kein fensterrahmen, andere größe) AWT, Swing, JavaFX & SWT 13
A JPanel größe verändern AWT, Swing, JavaFX & SWT 4
M SWT ScrollPane Größe zu klein AWT, Swing, JavaFX & SWT 6
T Swing Größe einer Komponente in einem BoxLayout / FlowLayout festlegen AWT, Swing, JavaFX & SWT 7
H JTree in JScrollPane passt sich nicht an Größe von JPanel an AWT, Swing, JavaFX & SWT 2
L JButton - Größe anders als erwartet AWT, Swing, JavaFX & SWT 2
L JDialog - Event wenn Parent größe ändert AWT, Swing, JavaFX & SWT 2
W GridBagLayout Größe geben AWT, Swing, JavaFX & SWT 1
S Swing JFrame hat nicht die Größe, die ich eingegeben habe AWT, Swing, JavaFX & SWT 3
S Größe der Komponenten, beim ändern der größe des Frames, mit ändern! AWT, Swing, JavaFX & SWT 2
S Größe und Farbe vom JButton festlegen AWT, Swing, JavaFX & SWT 2
D Swing Jlist Größe während der Laufzeit verändern. AWT, Swing, JavaFX & SWT 11
H AWT Fenster- und JLabel-Größe automatisch anpassen AWT, Swing, JavaFX & SWT 2
T Swing Größe des Randes AWT, Swing, JavaFX & SWT 2
C LayoutManager JFrame größe und ausrichtung + Position von Fensterelementen AWT, Swing, JavaFX & SWT 2
B Swing JTable mit Daten - Reihen-Größe anpassen AWT, Swing, JavaFX & SWT 0
D SWT Window passt Größe nicht an AWT, Swing, JavaFX & SWT 4
N JPanel größe wissen/festlegen vor dem Anzeigen AWT, Swing, JavaFX & SWT 3
U Größe eines Button im Menü ändern AWT, Swing, JavaFX & SWT 1
G JavaFX Größe der Parentknoten AWT, Swing, JavaFX & SWT 5
R JPanel-Größe verändert sich nicht. Warum? AWT, Swing, JavaFX & SWT 5
T Swing Aktuelle Größe eines Textes in einem Label darstellen AWT, Swing, JavaFX & SWT 3
A JPanel oder GridLayout Größe festsetzten AWT, Swing, JavaFX & SWT 4
F Swing JComboBox - Frage zur Größe AWT, Swing, JavaFX & SWT 11
X Swing Größe eines Fensters JFrame / Frame AWT, Swing, JavaFX & SWT 5
SimonRap Swing JFrame Größe zur Laufzeit ändern AWT, Swing, JavaFX & SWT 2
G 2D-Grafik Größe der JFrame Decorations herausfinden? AWT, Swing, JavaFX & SWT 4
O Swing Jpanel autom. auf JFrame Größe bringen AWT, Swing, JavaFX & SWT 6
M Swing JLabel mit fester größe nachträglich formatieren AWT, Swing, JavaFX & SWT 2
A JComponent Größe AWT, Swing, JavaFX & SWT 8
S Größe von Panel verändern welches auf anderem Panel sitzt AWT, Swing, JavaFX & SWT 10
B JTextArea Größe an Container anpassen AWT, Swing, JavaFX & SWT 2
S Swing TextPane größe beschränken AWT, Swing, JavaFX & SWT 2
R Ellipse2D ändert Größe AWT, Swing, JavaFX & SWT 3
H Swing JButton größe ändern AWT, Swing, JavaFX & SWT 5
G JScrollPane reagiert nicht auf Änderung der JPanel-Größe AWT, Swing, JavaFX & SWT 4
P JPanel Größe ändern AWT, Swing, JavaFX & SWT 22
I Größe eines rotierten Images AWT, Swing, JavaFX & SWT 3
C Button Größe einstellen klappt nicht (setBounds) AWT, Swing, JavaFX & SWT 8
S 2D-Grafik Canvas Problem(Größe) AWT, Swing, JavaFX & SWT 6
R Größe/Anordnung der Gui-Elemente automatisch? AWT, Swing, JavaFX & SWT 6
S Die größe eines JButton ändern AWT, Swing, JavaFX & SWT 7
U feste Größe für den Zeichenbereich eines JFrames AWT, Swing, JavaFX & SWT 4
L Graphics.drawImage() - Output-Größe entspricht nicht Parametern AWT, Swing, JavaFX & SWT 10
P Tatsächliche Größe für Applet AWT, Swing, JavaFX & SWT 3
C Swing GridBag-Probleme (Größe und Ausrichtung) AWT, Swing, JavaFX & SWT 3
K JFrame Größe ändern AWT, Swing, JavaFX & SWT 4
M jTable - Größe beim Erzeugen AWT, Swing, JavaFX & SWT 4
hdi Swing JFrame Größe ermitteln AWT, Swing, JavaFX & SWT 6
Z größe der komponenten bestimmen AWT, Swing, JavaFX & SWT 16
X Alte Frame-Größe beim wiederholten Aufruf AWT, Swing, JavaFX & SWT 5

Ähnliche Java Themen

Neue Themen


Oben