# SWT - widget dynamisch erzeugen und anzeigen



## Choleriker (2. Jan 2012)

Hey,

mit SWT möchte ich bei Klick auf einen Knopf ein neues Widget erzeugen und anzeigen lassen.
Ich habe bereits einen Listener registriert und das Ereignis wird auch ausgelöst. Das neue Widget (im Testfall ein Label) wird auch erzeugt, aber nicht angezeigt.


```
public void addLabel() {
		Label newLab = new Label(outerOrderComp, SWT.None);
		newLab.setText("test");
		newLab.setVisible(true);
	}
```

Im Testfall ist es ein Label, aber eigentlich soll es ein Composite mit mehreren Widgets sein.
Ich habe im Forum gesehen, dass es das gleiche Problem schon mit Swing gab und wohl mit dem Aufruf von validate() gelöst wird. Aber wie funktionierts mit SWT?


Was mache ich falsch?

VG


----------



## Sonecc (3. Jan 2012)

Du musst die Composite (ggf. auch dessen Parent) zu einem layout auffordern.
also in deinem Fall:


```
outerOrderComp.layout(true, true);
```


----------



## achillesat (3. Jan 2012)

Muss du das neue Widget nicht noch mit  der Methode 
	
	
	
	





```
.add
```
 hinzufügen?


----------



## Sonecc (3. Jan 2012)

Es gibt in SWT keine add() methode...


----------



## Choleriker (3. Jan 2012)

hm, erstmal danke für den Hinweis.
Ich führe 

layout(true, true);

für das umliegenden Composite, dessen umschließende Gruppe und der Shell aus, aber das Label wird immer noch nicht angezeigt. Woran liegt das denn? Das Event wird wirklich ausgelöst.

Nebenbei: das umliegende outerOrderComp hat ein FillLayout.

Muss ich noch irgendwie update oder ähnliches ausführen? Wieso steht so etwas nicht mal in einem Tutorial?

VG


----------



## Sonecc (3. Jan 2012)

Also ich selbst hab das mal machen müssen und hab da auch etwas frickeln müssen, weil es schwer ist etwas vergleichbares zu finden.
Ich musste bei mir aber auch die Controls, die dem Composite angehängt waren löschen und neue anhängen.
Das mache ich wie folgt:

- Alle Children des Composites disposen (sollte für dich nicht nötig sein)
- Alle neuen Controls anhängen (Im prinzip so wie du es getan hast)
- Layout neu setzen (könnte bei dir eventuell auch noch helfen)
- Parent der composite zum relayout auffordern (machst du ja mehrfach)

Versuchs also mal damit das Layout neu zu setzen und rufe dann nochmal layout(true, true) auf


----------



## Choleriker (3. Jan 2012)

Also, ich teste es jetzt so

```
public void addLabel() {
		Label newLab = new Label(outerOrderComp, SWT.None);
		newLab.setText("test");
		newLab.setVisible(true);
		outerOrderComp.setLayout(new FillLayout(SWT.HORIZONTAL));
		outerOrderComp.layout(true, true);
		grpOrders.layout(true, true);
		shlTailorshop.layout(true, true);
	}
```

Aber auch hier nix. Ist es irgendetwas banales, das ich übersehe?
Kann doch nicht sein, dass ich alle umliegenden Layouts (FormLayout) neu setzen muss, oder?

Ist das nicht etwas halbwegs gängiges zur Laufzeit ein Label zu erzeugen? Habe schon einiges gesucht, aber anscheinend falsch.


----------



## Sonecc (3. Jan 2012)

Folgendes funktioniert bei mir problemlos:


```
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;

public class DynamicCompShell {

	public static void main(String[] args) {
		Display display = Display.getDefault();
		Shell shell = new Shell(display);
		shell.setLayout(new FillLayout(SWT.HORIZONTAL));

		Group grpTest = new Group(shell, SWT.NONE);
		grpTest.setText("Test");
		grpTest.setLayout(new FillLayout(SWT.HORIZONTAL));

		Composite btnComp = new Composite(grpTest, SWT.NONE);
		btnComp.setLayout(new FillLayout(SWT.HORIZONTAL));
		final Composite labelComp = new Composite(grpTest, SWT.NONE);

		Button btnAdd = new Button(btnComp, SWT.NONE);
		btnAdd.addSelectionListener(new SelectionAdapter() {

			@Override
			public void widgetSelected(SelectionEvent e) {
				addLabel(labelComp);
			}
		});
		btnAdd.setText("Add");

		shell.open();
		shell.layout();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}

	}

	public static void addLabel(Composite labelComp) {
		Label newLab = new Label(labelComp, SWT.None);
		newLab.setText("test");
		newLab.setVisible(true);
		labelComp.setLayout(new FillLayout(SWT.HORIZONTAL));
		labelComp.layout(true, true);
	}
}
```


----------



## Choleriker (3. Jan 2012)

Danke für das ausführliche Beispiel. Momentan kann ich aber nicht erkennen, warum das Beispiel funktioniert (das geht bei mir auch), mein Code aber nicht.

Ich habe einen Controller mit einer Methode registerListeners (Auszug):

```
window.getNewOrderBtn().addMouseListener(new MouseAdapter() {
			@Override
			public void mouseUp(MouseEvent e) {
				window.addLabel();
			}
		});
```

window ist vom Typ der GUI. Der Controller ruft die open Methode der GUI, die wiederum createContents() ruft und danach die Ereignisschleife startet.

und dann die GUI (Auszug):

```
public void addLabel() {
		Label newLab = new Label(outerOrderComp, SWT.None);
		newLab.setText("test");
		newLab.setVisible(true);
		outerOrderComp.setLayout(new FillLayout(SWT.HORIZONTAL));
		outerOrderComp.layout(true, true);

	}
```

Ich teste auch in addLabel() den Text der umschließenden Gruppe zu ändern. Nix.


----------



## Stelufl (4. Jan 2012)

Gib mal bitte etwas mehr Code. Das Label wird erzeugt, ja, ist sicherlich auch auf deiner Shell, ist aber nicht sichtbar/ist versteckt.


----------



## Sonecc (4. Jan 2012)

ich würde auch sagen, dass etwas mehr code notwendig ist


----------

