# JTextArea in GridBagLayout mit JScrollPane



## Bash (4. Feb 2005)

Hallole,

hab in dieser Konstellation (JTextArea in GridBagLayout mit JScrollPane) ein Problem, zu dem ich trotz vielen Experimenten und langem Suchen keine Lösung finden konnte. Vielleicht geht´s ja auch nicht. Aber wenn´s geht, dann weiß hier bestimmt jemand Rat   


Ich möchte Panels basteln, die z.B. so aussehen:

```
+-----------------------+
|+---------------------+|
||                     ||
||  JTextArea          ||
||                     ||
|+---------------------+|
|+--------++-----------+|
|| JLabel || JLabel    ||
|+--------++-----------+|
+-----------------------+
```

Das ist im Prinzip kein Problem und funktioniert auch weit gehend so, wie ich mir das vorstelle, wenn ich keine JScrollPane verwende. D.h. wenn das Fensterle in der Größe verändert wird, dann passt die JTextArea so an das Fenster an, wie ich es mir wünsche.

Dabei gibt es natürlich das Problemchen, dass die Fläche so klein werden kann, dass nicht mehr alles im Panel zu sehen ist.
Nichts leichter als das, dachte ich. Tust du das JPanel halt in eine JScrollPane und der Kittel ist geflickt.

Weit gefehlt. Jetzt wird nämlich die JTextArea unartig und geht mir damit gewaltig auf den Geist.
Wenn die Panel-Größe jetzt verändert wird, dann passt die Größe der JTextArea sich auch an, aber blödsinnig:
Die Höhe schrumpft nur und wächst nie, während sie in der Breite nur wächst, aber nie schrumpft.
Das macht keinen Sinn.

Was kann ich tun
- damit das Panel ScrollBars bekommt, wenn nicht mehr alles drauf passt und
- dass gleichzeitig die JTextArea immer so breit ist wie das Panel und in der Höhe entsprechend wächst/schrumpft?

Würde mich riesig freuen, wenn jemand dafür eine Lösung hätte!

Gruß,
Bash



Hier der Beispiel-Code. Mit der Variablen "mitScrollPane" kann man den Unterschied (mit/ohne JScrollBar) vergleichen.


```
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;

public class JTextAreaProblem
extends JFrame {
	private boolean mitScrollPane = false;

	public static void main(String[] args) {
		new JTextAreaProblem();
	}
	public JTextAreaProblem() {
		super("");
		füllen();
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setSize(200, 150);
		setLocationRelativeTo(null);
		setVisible(true);
	}
	private void füllen() {
		JPanel panel = new JPanel();
		if (mitScrollPane) {
			getContentPane().add(new JScrollPane(panel));
		} else {
			getContentPane().add(panel);
		}
		GridBagLayout layout = new GridBagLayout();
		GridBagConstraints c = new GridBagConstraints();
		panel.setLayout(layout);

		JTextArea textArea = new JTextArea(
				"Dies ist ein beliebiger Text," +
				" der absichtlich so in die Länge gezogen wurde, " +
				" dass er mehrere Zeilen beansprucht.");
		textArea.setLineWrap(true);
		textArea.setWrapStyleWord(true);

		c.gridx = 0;
		c.gridy = 0;
		c.fill = GridBagConstraints.HORIZONTAL;
		c.weightx = 2;		// andere Werte scheinen nix zu ändern
		c.weighty = 0;		// dito
		c.gridwidth = 2;	// GridBagConstraints.REMAINDER hilft auch net
		layout.setConstraints(textArea, c);
		panel.add(textArea);

		c.gridwidth = 1;
		c.gridy = 1;
		c.weightx = 0;
		JLabel links = new JLabel("linkes Label");
		links.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
		layout.setConstraints(links, c);
		panel.add(links);

		c.gridx = 1;
		c.weightx = GridBagConstraints.REMAINDER;
		JLabel rechts = new JLabel("rechtes Label");
		rechts.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
		layout.setConstraints(rechts, c);
		panel.add(rechts);
	}
}
```


----------



## Illuvatar (4. Feb 2005)

Ich würde das an deiner Stelle so lösen:

```
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;

public class JTextAreaProblem extends JFrame {
   private boolean mitScrollPane = true;
   public static void main(String[] args) {
      new JTextAreaProblem();
   }
   public JTextAreaProblem() {
      super("");
      füllen();
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      setSize(200, 150);
      setLocationRelativeTo(null);
      setVisible(true);
   }
   private void füllen() {
      JPanel panel = new JPanel();
      getContentPane().add(panel);
      panel.setLayout(new BorderLayout(5, 5));
      JTextArea textArea = new JTextArea(
            "Dies ist ein beliebiger Text," +
            " der absichtlich so in die Länge gezogen wurde, " +
            " dass er mehrere Zeilen beansprucht.");
      textArea.setLineWrap(true);
      textArea.setWrapStyleWord(true);
      if (mitScrollPane)
         panel.add("Center", new JScrollPane (textArea));
      else
         panel.add("Center", textArea);
      JPanel pan = new JPanel();
      pan.setLayout(new GridLayout(1, 2, 5, 5));
      JLabel links = new JLabel("linkes Label");
      links.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
      pan.add(links);
      JLabel rechts = new JLabel("rechtes Label");
      rechts.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
      pan.add(rechts);
      panel.add("South", pan);
   }
}
```


----------



## Guest (5. Feb 2005)

@Illuvatar: Danke für die Antwort, aber leider ist diese Lösung nicht das, was ich suche.

BorderLayout und/oder GridLayout sind für meine Zwecke nicht geeignet, ich brauche ein GridBagLayout. 

Will ich kurz erläutern:
Ich muss eine ganze Reihe von Panels mit immer der gleichen Methode mit sehr unterschiedlichen Inhalten füllen.
Links sollen meistens (manchmal auch nicht) Labels stehen und rechts daneben die gelabelten Items (JLabel, JTextField, JComboBox, JTextArea usw.).
Die "linke Spalte" (d.h. die Labels am linken Rand) sollen ihre Breite nie verändern, aber ihre vertikale Position an die der  Items rechts daneben anpassen, während die rechten Items den verfügbaren restlichen Platz je nach Item-Typ ausnutzen sollen.

Bei einem GridLayout habe ich den Nachteil, dass die Zellen-Höhe unabhängig vom Zellen-Inhalt für alle Zeilen gleich groß ist.
Ein JTextField bekommt dann die gleiche Höhe wie eine JList. Das verbraucht unnötig Platz und sieht nicht gut aus.
Außerdem bleibt dann die Breite der linken Spalte nicht konstant.

Mit einem SpringLayout hab ich´s auch schon probiert, aber das ging total daneben.
GridBagLayout scheint mir genau das Richtige für meine Anwendung zu sein, wenn da nur nicht diese widerspenstigen JTextAreas wären.

Wäre schön, wenn ich noch eine Lösung finden könnte.
Wenn´s nicht geht, dann wär´s wahrscheinlich schon hilfreich, wenn ich wenigstens wüsste warum.


----------



## sofa-surfer (5. Feb 2005)

Warum geht das nicht mit nem BorderLayout?
Du nimmst ein "main"-panel, packst am NORTH-Ende das obere Dingens drauf. Am SOUTH-Ende nimmst du ein zweites Panel, was wieder mit nem BorderLayout versehen ist. Auf der WEST-Seite das linke Label, und im CENTER-Bereich das rechte Item, was dann immer soviel Platz bekommt, wie noch da ist. Das linke Item ist in der Breite fest und du kannst es bei Bedarf mit noch nem weiteren Layout dorthin positionieren wo du willst ...
Das entspricht meiner Meinung deiner obigen Beschreibung (?)


----------



## Bash (5. Feb 2005)

@sofa-surfer:
Danke für den gut gemeinten Rat.
Aber das Problem, das ich beschrieben habe, kann ich mit einem BorderLayout vermutlich nicht lösen.

In meiner Anfangs-Skizze und dem Beispiel-Code habe ich ein möglichst einfaches Beispiel dargestellt, um zu zeigen
- DASS,
- WANN und

- WIE
 das Problem auftritt.

Wenn ich eine Skizze und ein Programm-Teil dargestellt hätte, aus denen hervor gegangen wäre,
- WARUM
das Problem auftritt, dann hätte man mich vermutlich aufgefordert, das Problem erst mal zu reduzieren.

Also zeige ich jetzt mal ein ganz anderes Panel, das von der gleichen Methode erstellt werden soll, in dem zwei JTextAreas (eins mit und eins ohne Label) auftauchen.

Ich sehe nicht, wie man dieses Panel besser in ein BorderLayout hinein GENERIEREN kann, als in ein GridBagLayout.
Andererseits hätte ich damit bei einem GridBagLayout überhaupt kein Problem - vorausgesetzt JTextArea würde sich immer gleich verhalten, unabhängig davon, ob das hier dargestellte Panel auf einer JScrollBar sitzt oder nicht.

D.h.: Bis jetzt bin ich - leider - noch nicht weiter gekommen.  :cry: 


```
+----------------------------------------------------------------+
|+-------------++-----------------------------------------------+|
|| JLabel      || JTextArea                                     ||
|+-------------+|                                               ||
|               |                                               ||
|               |                                               ||
|               +-----------------------------------------------+|
|+-------------++-----------------------------------------------+|
|| JLabel      || JTextField                                    ||
|+-------------++-----------------------------------------------+|
|+-------------++-----------------------------------------------+|
|| JLabel      || JList                                         ||
|+-------------+|                                               ||
|               |                                               ||
|               |                                               ||
|               +-----------------------------------------------+|
|+-------------++-----------------------------------------------+|
|| JLabel      || JLabel                                        ||
|+-------------++-----------------------------------------------+|
|+-------------++-----------------------------------------------+|
|| JLabel      || JTextField                                    ||
|+-------------++-----------------------------------------------+|
|+--------------------------------------------------------------+|
|| JCheckBox                                                    ||
|+--------------------------------------------------------------+|
|+--------------------------------------------------------------+|
|| JCheckBox                                                    ||
|+--------------------------------------------------------------+|
|+--------------------------------------------------------------+|
|| JCheckBox                                                    ||
|+--------------------------------------------------------------+|
|+--------------------------------------------------------------+|
|| JTextArea                                                    ||
||                                                              ||
||                                                              ||
|+--------------------------------------------------------------+|
.                                                                .
.                   ... und so weiter ...                        .
.                                                                .
|+-------------++-----------------------------------------------+|
|| JLabel      || JLabel                                        ||
|+-------------++-----------------------------------------------+|
+----------------------------------------------------------------+
```


----------



## Bash (6. Feb 2005)

Hab jetzt selbst eine Lösung gefunden, mit der ich erst mal zufrieden bin. 

Für den Fall, dass noch jemand mit einer ähnlichen Situation kämpfen sollte, hänge ich meine "Lösung" unten an.
Mein Problem hab ich dadurch gelöst, dass ich an das Panel einen ComponentAdapter gehängt habe, der beim Panel-Resize das JTextArea auffordert, sich an die neue Panel-Größe anzupassen.
Die JTextArea pass sich bei Bedarf an die Breite des VisibleRects an.
Für die Text-Felder braucht´s in dieser Lösung eine eigene Klasse (MeinTextArea), die JTextArea um diese Methode ergänzt.

Das Ganze ist so noch nicht besonders generisch, weil der Adapter alle Areas kennen muss, die sich anpassen sollen.
Aber das ist eine andere Geschichte, die ich hoffentlich auch noch in den Griff bekomme.

Falls jemandem noch was dazu einfallen sollte: ich bin ganz Ohr ;-)


```
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;

public class JTextAreaProblem
extends JFrame {
	JPanel panel;
	MeinTextArea textArea;
	GridBagLayout layout;
	GridBagConstraints c = new GridBagConstraints();

	public static void main(String[] args) {
		new JTextAreaProblem();
	}
	public JTextAreaProblem() {
		super("");
		füllen();
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setSize(200, 150);
		setLocationRelativeTo(null);
		setVisible(true);
	}
	private void füllen() {
		panel = new JPanel();
		getContentPane().add(new JScrollPane(panel));
		panel.addComponentListener(
				// Dieser Adapter soll natürlich nicht nur ein JTextArea informieren,
				// sondern alle.
				new ComponentAdapter() {
				public void componentResized(ComponentEvent ce) {
					textArea.anpassen(panel);
				}
			}
		);
		layout = new GridBagLayout();
		panel.setLayout(layout);

		c.fill = GridBagConstraints.HORIZONTAL;
		c.gridx = 0;
		c.weightx = 1;
		c.gridwidth = 2;
		textArea = new MeinTextArea(
			"Dies ist ein beliebiger Text," +
			" der absichtlich so in die Länge gezogen wurde, " +
			" dass er mehrere Zeilen beansprucht.");
		textArea.setWrapStyleWord(true);
		textArea.setLineWrap(true);
		layout.setConstraints(textArea, c);
		panel.add(textArea);

		JLabel links = new JLabel("links");
		links.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
		c.gridx = 0;
		c.gridy = 1;
		c.gridwidth = 1;
		c.weightx = 0;
		layout.setConstraints(links, c);
		panel.add(links);

		JLabel rechts = new JLabel("rechts");
		rechts.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
		c.gridx = 1;
		c.weightx = 1;
		layout.setConstraints(rechts, c);
		panel.add(rechts);
	}
	private class MeinTextArea
	extends JTextArea {
		public MeinTextArea(String text) {super(text);}
		public void anpassen(JPanel panel) {
			// Die JTextArea passt sich immer dann an, wenn das Panel breiter als
			// die sichtbare Fläche ist.
			if (panel.getSize().width > panel.getVisibleRect().width) {
				Dimension dim = getSize();
				dim.width = panel.getVisibleRect().width - getLocation().x;
				setSize(dim);
			}
		}
	}
}
```


----------

