# TextArea relativ zur Fenstergröße



## manuche (29. Okt 2007)

Hallo!
Ich schreibe ein Programm und würde gerne, das mein TextFeld sich vergrößert, wenn man das ganze Fenster vergrößert bzw. verkleinert soll sich das Textfeld auch vergrößern bzw verkleinern... dabei soll es aber nicht unendlich klein werden, sondern nur bis zu einer bestimmten größe!
Ich erwarte jetzt nicht unbedingt Quellcode sondern eher nen paar Ansätze wo ich mich leicht einlesen kann bzw. womit ich rum experimentiern kann!
Danke schonmal!!!


----------



## The_S (29. Okt 2007)

Schau dir doch mal die unterschiedlichen Layoutmanager an.


----------



## wayne (29. Okt 2007)

das macht eigentlich jeder normale LayoutManager, also FlowLayout, GridLayout, BorderLayout, etc.. mit dem LayoutManager GridBagLayout kannst du da sogar noch etwas spezifischer werden, indem du dem textfeld abstände zum rand sowie eine vergrößerte fläche (letzten zwei parameter von GridBagConstraints, also ipadx und ipady) zuteilen kannst.

ansonsten gibt es nur das eine für dich, daß du die größe deines textfeldes selbst berechnest, also einen eigenen LayoutManager schreibst.

viel erfolg

wayne


----------



## manuche (29. Okt 2007)

Also brauch ich quasi einen WindowListener... Wenn das Fenster sich verändert muss ich berechnen wie groß es wird und dementsprechend mein TextFeld verändern...
Dann noch ein repaint und gut ists???
na das hab ich mir einfacher vorgestellt xD


----------



## The_S (29. Okt 2007)

es ist auch einfacher. Einfach kein Null-Layout verwenden (was man ohnehin nicht machen sollte), sondern nen ordentlichen Layout-Manager, der das für dich erledigt!


----------



## wayne (29. Okt 2007)

und wenn du dir nen LayoutManager selbst schreibst, wird der immer gefragt werden, welche größe dein textfeld erhalten soll, sobald die oberfläche, für die du ihn einteilst, neu berechnet werden soll. also auch beim verändern der größe des anzeigenden fensters.


----------



## manuche (29. Okt 2007)

Hab mir jetzt was im Galilieo OpenBook und ich denke, das ist genau das was ich brauche aber irgendwie funtkioniert das nicht so wie ichs gern hätte...
Also gibts bei leo.org die rubrik änfänger - galileoOpenBook??? 

GridBagLayout


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


public class Programmextends JFrame{
  private JMenuBar menu = new JMenuBar();
  private JMenu file = new JMenu("Datei");
  private JMenuItem open = new JMenuItem("Öffnen");
  private JMenuItem save = new JMenuItem("Speichern");
  private JMenuItem saveAs = new JMenuItem("Speichern als");
  private JMenuItem exit = new JMenuItem("Beenden");
  private JMenu edit = new JMenu("Bearbeiten");
  private JMenuItem mark = new JMenuItem("Markieren");
  private JMenuItem copy = new JMenuItem("Kopieren");
  private JMenuItem cut = new JMenuItem("Ausschneiden");
  private JMenuItem paste = new JMenuItem("Einfügen");
  private JMenu help = new JMenu("Hilfe");
  private JMenuItem vInfo = new JMenuItem("Info");
  private JMenuItem helpsec = new JMenuItem("Hilfe");
  private JToolBar toolmenu = new JToolBar();
  private JButton toolSave = new JButton("picS");
  private JButton toolOpen = new JButton("picO");
  private JTextArea textBlock = new JTextArea();
  
    //aus dem GalileoOpenBook
  static void addComponent( Container cont, GridBagLayout gbl, Component comp, 
                                          int x, int y, int width, int height, double weightx, double weighty ){
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.fill = GridBagConstraints.BOTH;
    gbc.gridx = x; gbc.gridy = y;
    gbc.gridwidth = width; gbc.gridheight = height;
    gbc.weightx = weightx; gbc.weighty = weighty;
    gbl.setConstraints( comp, gbc );
    cont.add( comp );
  }

  public Programm(String title) {
    super(title);
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) { System.exit(0); }
    });
    Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
    int frameWidth = d.width - 80;
    int frameHeight = d.height - 80;
    setSize(frameWidth, frameHeight);
    int x = 30; //(d.width - getSize().width) / 2;
    int y = 30; //(d.height - getSize().height) / 2 ;
    setLocation(x, y);
    Container cp = getContentPane();
    GridBagLayout gbl = new GridBagLayout();
    cp.setLayout(gbl);
    setExtendedState(MAXIMIZED_BOTH);

    file.add(open);
    ...
    file.add(save);
    ...
    file.add(saveAs);
    ...
    file.add(exit);
    ...
    menu.add(file);

    edit.add(mark);
    ...
    edit.add(copy);
    ...
    edit.add(cut);
    ...
    edit.add(paste);
    ...
    menu.add(edit);
    ...
    help.add(helpsec);
    ...
    help.add(vInfo);
    ...
    menu.add(help);
    setJMenuBar(menu);
    
    
    toolSave.addActionListener(new ActionListener(){
    ...
    toolmenu.add(toolSave);
    ...
    toolmenu.add(toolOpen);

    textBlock.setBounds(10, 50, frameWidth - 30, frameHeight - 100);
    
    //aus dem GalileoOpenBook
    addComponent(cp, gbl, toolmenu, 0, 0, 2, 2, 0, 0);
    addComponent(cp, gbl, textBlock, 0, 0, 2, 10, 0, 0);
    
    setResizable(true);
    setVisible(true);
  }
}
```

Problem ist halt (ums mal aufn Punkt zu bringen) dass er nicht untereinander schreibt...
wenn ich bei 0/0 etwas positioniere welches 50x50 groß ist so fängt das nächste objekt erst bei 50/50 an...
sieht halt nich nur scheisse aus!


----------



## wayne (29. Okt 2007)

vielleicht solltest du kurz was zu GridBagLayout erfahren. GridBagLayout ist das der schwerste aller LayoutManager, jedoch auch derjenige, der dir am meißten gestalterische freiheit erlaubt. GridBagLayout unterteilt dir deine oberfläche in bereiche, welche du durch die angaben x und y ansteuern kannst. dein parent wird dabei in soviele teile unterteilt, wie dein größter x und größter y wert groß ist, plus natürlich die größe width und height, falls eine der Componenten mehr als nur eine zelle benötigt, weil sie einfach breiter ist, als andere Components in gleicher Zeile oder Spalte. die Components belegen dabei vorrangig den platz, den sie benötigen (zu ermitteln mittels getPreferredSize()). ist mehr platz verfügbar, so verhält sich der LayoutManager entsprechend den vorgegebenen parametern für die einzelnen Components. darf er sie horizontal oder vertikal vergrößern um den platz zu nutzen (GridBagConstraints.HORIZONTAL, GridBagConstraints.VERTICAL und GridBagConstraints.BOTH) und welche Component ist dabei zu bevorzugen (weightx und weighty). letzteres sind übrigends double-werte im wertebereich von 0.0 bis 1.0. 

dein problem wirst du warscheinlich gelöst bekommen, wenn du dein textfeld und das toolmenü folgendermaßen hinzufügst:

```
addComponent(cp, gbl, toolmenu, 0, 0, 1, 1, 1.0, 0.0); 
addComponent(cp, gbl, textBlock, 0, 1, 1, 1, 1.0, 1.0);
```

viel erfolg

wayne


----------



## manuche (30. Okt 2007)

Also ich verstehe das wie folgt: (korrigiert mich wenn's falsch ist)

- x und y bestimmen die Position des Objektes im Layoutmanager
- width und heigth geben an wie viel platz ich einem Objekt an dieser Stelle zur Verfügung stelle
- weightx und weighty geben an wohin sich das aktuelle Objekt ausdehnen darf...(?)

Also klingt einleuchtend aber was ist, wenn ich möchte das sich ein Objekt überhaupt nich ausdehnt und verkleinert sondern nur die drumherum???
Und wofür genau stehen die double-Werte von weightx bzw weighty? Muss ja nen Sinn haben warum sie größer 0 bzw kleiner 1 sind...

Also ich hab grad ein Programm gefunden mit dem man sein Layout gestalten kann und es auch testen kann...
Das Programm heisst "The Cells"...
Werde das mal ausprobieren!

The Cells


----------



## Michael... (30. Okt 2007)

Für komplexere GUIs schreibe ich mir am liebsten einen eigenen LayoutManager - einfach die Klasse LayoutManager implementieren und in der Methode "public void layoutContainer(Container container)" die Lage und Grösse der Elemente definieren. Für die inneren Bereich kann man dann ja wieder auf die Standard LayoutManager zurückgreifen.

Ich persönlich meide das GridBagLayout und hatte bisher auch nur ganz wenige Anwendungen bei denen das GridBagLayout von Vorteil war.


----------



## wayne (30. Okt 2007)

ne, ganz verstanden hast du's noch nicht. zieh dir mal die beschreibung von GridBagLayout rein, beispielsweise von hier. dort findest du unter anderem auch 2 bilder von oberflächen welche mit buttons gefüllt sind. ich erklärs mal an dem linken bild. die buttons haben vermutlich alle GridBagConstraints.BOTH gesetzt bekommen, da sie ihre zellen komplett ausfüllen. sie dürfen sich also in horizontaler und vertikaler richtung entfalten. dazu haben sie vermutlich in x- und y-richtung das jeweilige weight auf 1.0 gesetzt bekommen, was bewirkt, daß wenn sich die oberfläche vergrößert der neu zur verfügung stehende platz gleichmäßig unter allen buttons verteilt wird (weil sie alle das gleiche gewicht haben). hätte einer davon beispielsweise 0.0 als gewicht gesetzt bekommen, so würde er gleich groß bleiben, wärend sich andere vergrößern bzw. würde sich verkleinern, wärend andere gleich groß bleiben (solange, bis er seine minimale größer erreicht hat).

die buttons 1 - 4 liegen alle in der ersten zeile, daß heißt, die haben alle y=0 und x=0 bis x=3. betrachte ich alle auf diesem panel platzierten buttons so sind diese buttons mit die kleinsten. deshalb erhalten alle width=1 und height=1. button5 hingegen sitzt eine zeile tiefer, wodurch er auf y=1 gesetzt wird und x=0, denn er beginnt ja an gleicher stelle, wie button1, der ebenfalls x=0 hat. nun ist button5 aber wesentlich breiter als button1, nämlich so breit, wie button1 + button2 + button3 + button4. letzterer sitzt auf x=3, also in der 4. zelle. dadurch ergibt sich für button5 width=4 und height=1, denn er ist ja genau so hoch, wie die buttons der 1. zeile. button6 sitzt wieder in einer neuen zeile, also y=2 und x=0. er ist nicht ganz so breit, wie button5. aus der betrachtung ergibt sich für button6 width=3 und height=1. es folg button7 mit x=3 und y=2. dieser ist wiederum nur eine zelle groß, also width=1 und height=1. button8 ist nun an x=0 und y=4 anzusiedeln. dieser ist gleichbreit wie button1, also eine zelle breit, aber zwei zellen hoch (zwei zellen, die erst im nachhinein durch das hinzufügen von button9 und button10 definiert werden). deshalb erhält button8 width=1 und height=2. button9 sitzt an x=1 und y=4 mit einer breite von width=3 und height=1. wenn es dies nun wäre, würde button8, trotzdem er mit height=2 angegeben wurde genau so hoch erscheinen, wie button9, da die zeile y=5 eine höhe von 0 pixeln aufweisen würde, da ja kein Component da ist, der ihr eine höhe verleiht. erst durch das hinzufügen von button10 in y=5 und x=1 mit width=3 und height=1 wird button8 höher als button9.

ich hoffe, daß war halbwegs verständlich. zu GridBagLayout gibts eigentlich haufenweise text zu lesen, da es nicht einfach ist, das ganze zu beschreiben. selbst ich, der ich es schon vielfach verwendet habe, muss nach dem aufbau eines Layouts immer wieder korrekturen an meinen parametern durchführen, bis das ganze so aussieht, wie ich es mir vorgestellt habe. von dem her drück ich dir die daumen und wünsche viel erfolg   

wayne


----------



## manuche (30. Okt 2007)

Ich habe mit dem Programm mal ein wenig rumexperimentiert und ich finde es ziemlich gut... also mit nem bisschen Motivation kann man da glaub ich einiges mit machen...

Ich hab allerdings ne Frage: Und zwar wird ja eine Art Tabelle (3x3) erstellt... Oben soll sich über alle 3 Spalten eine Toolbar erstrecken nur schaffe ich es nicht, dass sie die anderen spalten nicht verschiebt!
Wie kann ich das ändern bzw kann ich es überhaupt ändern?

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

public class Programm extends JFrame{
  // Anfang Variablen
  private JMenuBar menu = new JMenuBar();
  private JMenu file = new JMenu("Datei");
  private JMenuItem open = new JMenuItem("Öffnen");
  private JMenuItem save = new JMenuItem("Speichern");
  private JMenuItem saveAs = new JMenuItem("Speichern als");
  private JMenuItem exit = new JMenuItem("Beenden");
  private JMenu edit = new JMenu("Bearbeiten");
  private JMenuItem mark = new JMenuItem("Markieren");
  private JMenuItem copy = new JMenuItem("Kopieren");
  private JMenuItem cut = new JMenuItem("Ausschneiden");
  private JMenuItem paste = new JMenuItem("Einfügen");
  private JMenu help = new JMenu("Hilfe");
  private JMenuItem vInfo = new JMenuItem("Info");
  private JMenuItem helpsec = new JMenuItem("Hilfe");
  private JToolBar toolmenu = new JToolBar();
  private JButton toolSave = new JButton("picS");
  private JButton toolOpen = new JButton("picO");
  private JTextArea textArea = new JTextArea();

  private GridBagLayout layout = new GridBagLayout();
  private LayoutManager placeHolderL_layout = null;
  private LayoutManager placeHolderR_layout = null;
  private LayoutManager placeHolderT_layout = null;
  private JPanel placeHolderL = new JPanel();
  private JPanel placeHolderR = new JPanel();
  private JPanel placeHolderT = new JPanel();
  private JScrollPane textBlock = new JScrollPane();

  public Programm(String title) {
    super(title);
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) { System.exit(0); }
    });
    setLocation(0, 0);
    Container cp = getContentPane();
    GridBagLayout gbl = new GridBagLayout();
    cp.setLayout(gbl);
    setExtendedState(MAXIMIZED_BOTH);

    file.add(open);
    ...
    file.add(save);
    ...
    file.add(saveAs);
    ...
    file.add(exit);
    ...
    menu.add(file);

    edit.add(mark);
    ...
    edit.add(copy);
    ..
    edit.add(cut);
    ...
    edit.add(paste);
    paste.addActionListener(new ActionListener(){
    ...
    menu.add(edit);

    helpsec.addActionListener(new ActionListener(){
    ...
    help.add(helpsec);
    ...
    help.add(vInfo);
    menu.add(help);
    setJMenuBar(menu);
    
    toolmenu.add(toolSave);
    ...
    toolmenu.add(toolOpen);
    ...
    toolmenu.setFloatable(false);

    setLayout(layout);

    textBlock.getViewport().add(textArea);
    textArea.setText("Ich bin das Sheet");

    placeHolderL.setLayout(placeHolderL_layout);
    placeHolderR.setLayout(placeHolderR_layout);
    placeHolderT.setLayout(placeHolderT_layout);

    add(placeHolderR, new GridBagConstraints(4, 4, 1, 1, 1., 0.,
               GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
    add(placeHolderL, new GridBagConstraints(0, 4, 1, 1, 1., 0.,
               GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
    add(placeHolderT, new GridBagConstraints(2, 1, 1, 1, 0., 0.,
               GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
    add(textBlock, new GridBagConstraints(1, 2, 3, 3, 0., 1.,
               GridBagConstraints.NORTH, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 500, 200));
    add(toolmenu, new GridBagConstraints(0, 0, 1, 1, 1., 0.,
               GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 
Toolkit.getDefaultToolkit().getScreenSize().width, 0));
    
    setResizable(true);
    setVisible(true);
  }

  public static void main(String[] args) {
    new Programm("Programm");
  }
}
```

Einziger Unterschied ist, das ich es in dem Programm mit nem JPanel und nicht mit ner JToolBar gemacht habe... Aber kann daraus dann so nen Unterschied entstehen?


----------



## wayne (30. Okt 2007)

du willst doch, daß sich die größe des textfeldes ändert, die größe des toolbars aber gleich bleibt. also zunächst mal möchte ich auf deine placeholders eingehen. du addest da ein leeres panel links, rechts und über dem textfeld, unterhalb des toolbars. das kannst du dir sparen. dafür hält GridBagLayout dieses Insets-objekt bereit. dort kannst du in pixeln angeben, wieviel abstand dein textfeld haben soll. das nächste ist, daß du ipadx auf 500 und ipady auf 200 setzt. ipad ist die größe, die zur minimalen größe hinzugerechnet werden soll, sprich, wenn du text eingegeben hast, wird das textfeld nach erneuter layout-berechnung größer werden (solange halt der platz reicht), ohne daß du ansonsten was verändert hast. ist also nicht zielführend für deine geschichte, deshalb lasse beide werte lieber auf 0. ich kann zwar auch nur raten, da ich das jetzt nicht bei mir ausprobieren werde, ob's funktioniert, aber ich denke, die korreten parameter wären:

```
add(toolmenu, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.NORTH, 
               GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0),0,0));
add(textBlock, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, 
               GridBagConstraints.BOTH, new Insets(40, 40, 40, 40), 0, 0));
```
somit ist toolmenu berechtigt sich horizontal voll auszubreiten (wegen GridBagConstraints.HORIZONTAL) und sitzt oben in seiner zelle drin (wegen GridBagConstraints.NORTH). wenn du hier ebenfalls links und rechts abstand haben willst, mach einfach new Insets(0,40,0,40), davon ausgehend, daß du 40 pixel abstand wünschst. letzteres musst du halt deinem empfinden nach anpassen. dein textfeld sitzt darunter (wegen y=1) und darf sich horizontal und vertikal voll entfalten (wegen weightx=1.0 und weighty=1.0 und GridBagConstraints.BOTH). es sitzt mittig in seiner zelle und hat in alle richtungen 40 pixel abstand.

ansonsten hast du's aber schon richtig verstanden. es entsteht anhand der parameter, welche du den einzelnen Components mitgibst, eine tabelle. das sich einzelne spalten ändern und andere nicht, kannst du steuern, indem du allen Components, welche sich in einer spalte befinden, die sich nicht ändern soll, GridBagConstraints.VERTICAL bzw. GridBagConstraints.NONE mitgibst. dadurch dürfen sich diese nur vertikal oder gar nicht ändern. nur wenn alle Components in einer spalte so hinzugefügt wurden, daß sie sich nicht horizontal platz genehmigen dürfen, funktioniert das. auf der anderen seite muss aber in den daneben liegenden spalten dann eine Component liegen, die sich den überflüssigen platz krallt. ansonsten, wenn alle Components GridBagConstraints.NONE gesetzt bekamen, sollte sich eigentlich nur der platz zwischen den Components verändern.

viel erfolg

wayne


----------



## manuche (30. Okt 2007)

Da hat einer AHnung von der Materie... Hat alles super funktioniert und auch "ein wenig" verstanden... Zumindest hab ichs jetzt mal durcharbeitet und später wieder drauf zurück greifen!!!
Danke allen die sich die Mühe gemacht haben!!!
greetz manuche


----------



## manuche (5. Nov 2007)

Eine Frage ist mir allerdings noch eingefallen? Und zwar:
Was ist, wenn sich sich sonst alles verzerren darf, nur das Textfield in der mitte nicht... sodass dam Frame Scrollbars hinzugefügt werden wenn man das Fenster kleiner als das TextField macht???


----------

