Panel zu klein

Andi_CH

Top Contributor
Wenn ich das Progrämmchen starte, ist das Frame zu klein (unter der TextArea wird kein Abstand mehr angezeigt, obwohl da row9 = 20dlu und gleich wie 1 enigestellt ist).

Kann ich, wenn ja wie, verhindern, dass das zur Laufzeit mit der Maus Frame kleiner gemacht wird?

Seltsamerweise liefert panel.getSize
Code:
java.awt.Dimension[width=0,height=0]

Java:
import java.awt.Dimension;
import javax.swing.*;
import com.jgoodies.forms.layout.*;

public class Example2 {

	final static String text1 = "Textlabel 1";
	final static String text2 = "Text 2";
	final static String text3 = "Textlabel Nummer 3";
	final static String text = "Das ist der Megatext, der länger ist als die Breite des "+
	"verwendeten Feldes und umgebrochen werden sollte und mehrere Zeilen " +
	"lang ist.";

	private int rowCounter = 2;
	private CellConstraints cc = new CellConstraints();

	private void addRow(JPanel panel, JLabel label, JTextField field) {
		panel.add(label, cc.xy(2, rowCounter));
		panel.add(field, cc.xy(4, rowCounter));
		rowCounter += 2;
	}

	private JPanel createPanel() {
		String colSpec = "10dlu, pref, 10dlu, 30dlu, 10dlu";
		String rowSpec = "20dlu, pref, 5dlu, pref, 5dlu, pref, 5dlu, pref, 20dlu";
		FormLayout layout = new FormLayout(colSpec,rowSpec);

		layout.setRowGroups(new int[][]{{2, 4, 6}, {3, 5}, {1, 7, 9}});
		JPanel myPanel = new JPanel(layout);

		JLabel label1 = new JLabel(text1);
		JTextField field1 = new JTextField("Feld1");
		addRow(myPanel, label1, field1);

		JLabel label2 = new JLabel(text2);
		JTextField field2 = new JTextField("Feld2");
		addRow(myPanel, label2, field2);

		JLabel label3 = new JLabel(text3);
		JTextField field3 = new JTextField("Feld3");
		addRow(myPanel, label3, field3);

		JTextArea area = new JTextArea(text);
		area.setWrapStyleWord(true);
		area.setLineWrap(true);
		area.setEditable(false);
		myPanel.add(area, cc.xyw(2, rowCounter, 3));

		Dimension dim = myPanel.getSize();
		System.out.println(dim);
//liefert 0/0
		return myPanel;
	}

	public static void main(String[] args) {
		Example2 ex = new Example2();
		JFrame frame = new JFrame("Example2");
		frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
		frame.add(ex.createPanel());
		frame.pack();
		frame.setVisible(true);
	}
}
 
frame.setResizable(false);
Nicht ganz das richtige ... Mal präziser umschreiben ;-)

...ich es zwar grösser machen können, aber nicht kleiner als ein Mindestmass.


Die Größe kann erst bestimmt werden, wenn der Frame und das Panel darin sichtbar sind.

Kann doch so nicht stimmen - der Platzbedarf ist schon vorher bekannt. In der Zwischenzeit gefunden: getPreferredSize liefert beinahe das was ich brauche. Beinahe, weil die Höhe zu klein ist.
Die unterste, leere Zeile wird nicht berücksichtigt und erst noch ein Teil des Textfeldes abgeschnitten...

Aber nach einigen Versuchen staune ich erst recht!

Im createPanel:
Java:
System.out.println("panel.preferredSize = " + myPanel.getPreferredSize());

Im main:
Java:
System.out.println("frame.preferredSize = " + frame.getPreferredSize());
sleep(10); // Ist Thread.sleep mit leerem Exceptionhandler
System.out.println("frame.preferredSize = " + frame.getPreferredSize());

Ausgabe:
Code:
panel.preferredSize = java.awt.Dimension[width=234,height=191]
frame.preferredSize = java.awt.Dimension[width=250,height=229]
frame.preferredSize = java.awt.Dimension[width=250,height=293]

Der Unterschied zwischen panel und frame kann ich mir so knapp erklären - das Frame hat ja noch einen Rahmen, aber warum das frame nach einer Pause plötzlich mehr Platz beansprucht ist ja wohl nicht so klar.

EDIT: Es ist das Panel, das plötzlich mehr Platz beansprucht ---
Code:
panel.preferredSize = java.awt.Dimension[width=234,height=191]
frame.preferredSize = java.awt.Dimension[width=250,height=229]
panel.preferredSize = java.awt.Dimension[width=234,height=255]
frame.preferredSize = java.awt.Dimension[width=250,height=293]
panel.preferredSize = java.awt.Dimension[width=234,height=255]
frame.preferredSize = java.awt.Dimension[width=250,height=293]

Was läuft hier falsch?

--
(Bin ich wieder mal der Einzige mit so einem Problem? Was könnte besser gemacht werden? Wie ich an anderer Stelle ja gesagt habe ist das Formlayout historisch einfach so da - wenn es etwas einfacheres gibt, bitte ich um Hinweise)
 

Anhänge

  • Example2.png
    Example2.png
    16,6 KB · Aufrufe: 40
Zuletzt bearbeitet:
Nur die Eine - aber eigentlich nicht einmal die - offensichtlich wird ja ein falscher Wert geliefert, sonst wäre wohl das Panel nicht zu klein ?
 
Problem lokalisiert.

Es ist die Textarea - sobald die in der Höhe wächst (wenn der Text umgebrochen wird) bekommt das, das Frame nicht mit.

Wie sag ichs meinem Kinde - äh Frame 😀, dass es die Bruttogrösse zu übernehmen hat?
 
EDIT: Das vorhin war eine typische Montag-Morgen-Fehlinterpretation:
Also wie bekomme ich das hin das dass @*#"! (Das ist ein Comic-Fluch 🙂) Frame und/oder Panel die korrekte Grösse bekommt?

Warum ist der Rahmen zu klein? (Bin ich der einzige Mensch in diesem Forum der diesen Effekt beobachtet?)

Java:
import java.awt.Dimension;
import java.awt.event.*;
import javax.swing.*;
import com.jgoodies.forms.layout.*;

public class Example3 {
	final static boolean debug = false;

	final static String text1 = "Textlabel 1";
	final static String text2 = "Text 2";
	final static String text3 = "Textlabel Nummer 3";
	final static String textAreaText = "Das ist der Megatext, der länger ist als die Breite des "+
	"verwendeten Feldes und umgebrochen werden sollte und mehrere Zeilen " +
	"lang ist. Mal schauen wie sich das verhält";

	private int rowCounter = 2;
	private CellConstraints cc = new CellConstraints();
	private JPanel     myPanel;
	private JTextField field1;
	private JTextField field2;
	private JTextField field3;
	private JTextArea  textArea;

	private void addRow(JPanel panel, JLabel label, JTextField field) {
		panel.add(label, cc.xy(2, rowCounter));
		panel.add(field, cc.xy(4, rowCounter));
		rowCounter += 2;
	}

	private JPanel createPanel() {
		String colSpec = "10dlu, pref, 10dlu, 30dlu, 10dlu";
		String rowSpec = "20dlu, pref, 5dlu, pref, 5dlu, pref, 5dlu, pref, 20dlu";
		FormLayout layout = new FormLayout(colSpec,rowSpec);

		layout.setRowGroups(new int[][]{{2, 4, 6}, {3, 5}, {1, 7, 9}});
		myPanel = new JPanel(layout);

		JLabel label1 = new JLabel(text1);
		field1 = new JTextField("Feld1");
		field1.addActionListener(new Field1ActionListener());
		field1.addFocusListener(new Field1FocusListener());
		field1.setName("field1");
		addRow(myPanel, label1, field1);

		JLabel label2 = new JLabel(text2);
		field2 = new JTextField("Feld2");
		field2.addActionListener(new Field2ActionListener());
		field2.addFocusListener(new Field2FocusListener());
		addRow(myPanel, label2, field2);

		JLabel label3 = new JLabel(text3);
		field3 = new JTextField("Feld3");
		field3.setEditable(false);
		addRow(myPanel, label3, field3);

		textArea = new JTextArea(textAreaText);
		textArea.setWrapStyleWord(true);
		textArea.setLineWrap(true);
		textArea.setEditable(false);
		myPanel.add(textArea, cc.xyw(2, rowCounter, 3));
		return myPanel;
	}

	private class Field1ActionListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			System.out.println("Field1ActionListener.actionPerformed()");
			Object src = e.getSource();
			if (src != null) {
				System.out.println(((JTextField)src).getName());
			}
		}
	}

	private class Field1FocusListener implements FocusListener {

		private final String className = "Field1FocusListener";

		@Override
		public void focusGained(FocusEvent e) {
			System.out.println(className + ".focusGained() e = " + e);
			System.out.println("Id = " + e.getID());
		}

		@Override
		public void focusLost(FocusEvent e) {
			System.out.println(className + ".focusLost() e = " + e);
		}
	}

	private class Field2ActionListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			System.out.println("Field2ActionListener.actionPerformed()");
			Object src = e.getSource();
			if (src != null) {
				System.out.println(((JTextField)src).getName());
			}
		}
	}

	private class Field2FocusListener implements FocusListener {

		private final String className = "Field2FocusListener";

		@Override
		public void focusGained(FocusEvent e) {
			System.out.println(className + ".focusGained() e = " + e);
			System.out.println("Id = " + e.getID());
		}

		@Override
		public void focusLost(FocusEvent e) {
			System.out.println(className + ".focusLost() e = " + e);
		}
	}

	public static void main(String[] args) {
		Example3 ex = new Example3();
		JFrame frame = new JFrame("Example3");
		frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
		frame.add(ex.createPanel());
		frame.pack();
		frame.doLayout();
		frame.setVisible(true);
		Dimension dim = frame.getSize();
		frame.setMinimumSize(dim);
	}
}
 
Zuletzt bearbeitet:
2 Tipps:

1. Wenn du das FormLayout benutzt, dann benutze doch den FormBuilder ist doch viel leichter mit dem Layout umzugehen (hab ich dir aber schon mal gesagt 😉 ).

2. Würde ich bei einer Textarea immer erst die anzahl cols und row festlegen, damit hat die Area eine gewünschte Größe und wird richtig gelayoutet

Java:
package test;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.WindowConstants;

import com.jgoodies.forms.builder.DefaultFormBuilder;
import com.jgoodies.forms.layout.FormLayout;
 
public class Example3 {
    final static boolean debug = false;
 
    final static String text1 = "Textlabel 1";
    final static String text2 = "Text 2";
    final static String text3 = "Textlabel Nummer 3";
    final static String textAreaText = "Das ist der Megatext, der länger ist als die Breite des "+
    "verwendeten Feldes und umgebrochen werden sollte und mehrere Zeilen " +
    "lang ist. Mal schauen wie sich das verhält";
 
    private JTextField field1;
    private JTextField field2;
    private JTextField field3;
    private JTextArea  textArea;
 
    private JPanel createPanel() {
        String colSpec = "pref, 5dlu, pref:grow, 5dlu";
        FormLayout layout = new FormLayout(colSpec);

        DefaultFormBuilder builder = new DefaultFormBuilder(layout);
       
        field1 = new JTextField("Feld1");
        field1.setName("field1");
        builder.append(text1, field1);
        
        field2 = new JTextField("Feld2");
        builder.append(text2, field2);
        
        field3 = new JTextField("Feld3");
        field3.setEditable(false);
        builder.append(text3, field3);
 
        textArea = new JTextArea(5,5);
        textArea.setText(textAreaText);
        textArea.setWrapStyleWord(true);
        textArea.setLineWrap(true);
        textArea.setEditable(false);
        
        builder.append(new JScrollPane(textArea), 4);
        return builder.getPanel();
    }
 
    public static void main(String[] args) {
        Example3 ex = new Example3();
        JFrame frame = new JFrame("Example3");
        frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        frame.add(ex.createPanel());
        frame.pack();
        frame.setVisible(true);
    }
}
 
Danke.

FormLayout wird einfach überall im vorliegenden GUI schon eingesetzt, weil es (zitat) "Viel flexibler und einfacher sei" Ich kann das nicht beurteilen und der Aussagende weiss da in den Details auch nicht weiter.

Das mit dem FormBuilder habe ich wohl überlesen oder als nicht so wichtig eingestuft - sorry - nur was habe ich damit gewonnen? Ich sehe (noch) keinen Unterschied ausser dass das Textfeld jetzt einen Scrollbar hat. Nein, bitte nicht. Der ganze Text muss angezeigt werden!

Der kommt übrigens sprachabhängig aus properties-Files und ist zwar unterschiedlich lang, aber nicht "unendlich" gross, obwohl er ganz sicher in einer einzelnen Sprache eine Zeile höher wird als geplant ;-)

Wie finde ich denn die notwendig Anzahl cols und rows zur Laufzeit?
Die Breite wird vorgegeben, die Höhe soll sich automatisch anpassen, was ja auch in meiner Variante geht, aber der umgebende Kontext erfährt nichts davon.

Das Textfeld bricht automatisch um, hat alle Angaben und ist die somit einzige Instanz die weiss, wie hoch es selbst wird.

Ich habe zwar schon immer wieder den Verdacht, dass sehr vieles manuell gemacht werden muss was auch automatisch ginge, aber über Font, Auflösung etc die Höhe eines Feldes selbst berechnen zu müssen kann es ja auch nicht sein.

Warum kann mir ein Feld wie dieses nicht einfach (zur Laufzeit!) sagen wie hoch es ist?
 
Das mit dem FormBuilder habe ich wohl überlesen oder als nicht so wichtig eingestuft - sorry - nur was habe ich damit gewonnen? Ich sehe (noch) keinen Unterschied ausser dass das Textfeld jetzt einen Scrollbar hat. Nein, bitte nicht. Der ganze Text muss angezeigt werden!

Du brauchst keine Labels, kein extra Panel, du kannst einfache colSpan angeben, kannst einfacher in neue rows springen, ist übersichtlicher, weniger Code, hast halt einen programmatischen GUIBuilder.

Ansonsten ist das FormLayout viel flexibler als die anderen LayoutManager, also mit dem FormLayout habe ich bis jetzt eigentlich so gut wie alles hinbekommen.

BTW: Das waren nur Anmerkungen, hab nicht behauptet das es dein Problem löst 😛 😛... Muss mir nochmal genau anschauen wann die Area die größe bekommt.
 
Hm hm - nein, dieses Beispiel liegt nicht auf meiner Harddisk - nein, bei mir doch nicht 😳

Ich glaube nach diesem Hinweis mache ich hier mal zu.

Danke!
 

Zurück
Oben