SWT Resize und aktualisierung der gui

lumo

Top Contributor
Hallo

ich habe folgende dreistufiges gui.

einmal eine ScrolledComposite mit einer Composite als content.
dann kommt der Content rauf (eine Composite, auf die ich etwas zeichne und ein label darauf.
die composite berechnet selbst die größe die es braucht.

jetzt habe ich noch einen ControlListener der schaut wenns ein resize gibt...
so... jetzt starte ich das ganze teil und der content hat mal die richtige größe,
aber die scrolledComposite zeigt keine scrollbar.
wenn ich das fenster in der größe ändere poppt die scrollbar korrekt auf...
hab schon versucht das irgendwie auszulösen bin aber gescheitert...

hat jemand von euch eine idee??

hier der lauffähige code:


die app zum starten:
Java:
import org.eclipse.swt.SWT;

public class MapPreviewTest {

	protected Shell shell;

	/**
	 * Launch the application.
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			MapPreviewTest window = new MapPreviewTest();
			window.open();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Open the window.
	 */
	public void open() {
		Display display = Display.getDefault();
		createContents();
		shell.open();
		shell.layout();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
	}

	/**
	 * Create contents of the window.
	 */
	protected void createContents() {
		shell = new Shell();
		shell.setSize(450, 300);
		shell.setText("SWT Application");
		shell.setLayout(new GridLayout(1, false));

		MapsComposite maps = new MapsComposite(shell, SWT.NONE);
		maps.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
	}
}

die composite mit den einzelnen contents...
Java:
import java.util.ArrayList;

public class MapsComposite extends Composite implements ControlListener {

	private static final int VERTICAL_SPACING = 5;
	private Composite container;
	private ScrolledComposite sc;
	private List<MapComposite> maps = new ArrayList<MapComposite>();

	/**
	 * Create the composite.
	 * 
	 * @param parent
	 * @param style
	 */
	public MapsComposite(Composite parent, int style) {
		super(parent, style);
		GridLayout gridLayout = new GridLayout(1, false);
		gridLayout.horizontalSpacing = 0;
		gridLayout.marginHeight = 0;
		gridLayout.marginWidth = 0;
		gridLayout.verticalSpacing = 0;
		setLayout(gridLayout);

		sc = new ScrolledComposite(this, SWT.BORDER | SWT.V_SCROLL);
//		sc.addControlListener(this);
		sc.setAlwaysShowScrollBars(true);
		sc.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
		sc.setExpandHorizontal(true);
		sc.setExpandVertical(true);

		container = new Composite(sc, SWT.NONE);
		GridLayout gl_container = new GridLayout(1, false);
		gl_container.verticalSpacing = VERTICAL_SPACING;
		gl_container.marginHeight = 0;
		gl_container.marginWidth = 0;
		gl_container.horizontalSpacing = 0;
		container.setLayout(gl_container);
		sc.setContent(container);

		createContents();
		addControlListener(this);
	}

	private void createContents() {
		String[] samples = new String[] { "bild1.jpg", "bild2.jpg",
				"bild3.jpg" };

		for (int i = 0; i < samples.length; i++) {
			MapComposite composite = new MapComposite(container);
			composite.setBackgroundImage(Resources.getImage("/res//",
					samples[i]));
			composite.setMapName(samples[i].replace(".jpg", ""));
			maps.add(composite);
		}
	}

	@Override
	protected void checkSubclass() {
		// Disable the check that prevents subclassing of SWT components
	}

	@Override
	public void controlMoved(ControlEvent e) {
	}

	@Override
	public void controlResized(ControlEvent e) {
		updateSC();
	}
	
	public void updateSC(){
		System.out.println("updateSC()");
		int height = 0;
		for (int i = 0; i < maps.size(); i++) {
			System.out.println(sc.getBounds().width);
			System.out.println("kid# "+i+".height = "+maps.get(i).getBounds().height);
			height += maps.get(i).getBounds().height;
		}
		height += VERTICAL_SPACING * (maps.size() - 1);
		sc.setMinHeight(height);
	}
}

der content
Java:
import org.eclipse.swt.SWT;

public class MapComposite extends Composite implements PaintListener,
		ControlListener {
	private Image bg;
	private GridData griddata;
	private float ar; // aspectRatio
	private Label lblMapName;

	/**
	 * Create the composite.
	 * 
	 * @param parent
	 * @param style
	 */
	public MapComposite(Composite parent) {
		super(parent, SWT.NO_BACKGROUND | SWT.DOUBLE_BUFFERED);
		this.griddata = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1);
		setLayoutData(griddata);
		setBackgroundMode(SWT.INHERIT_DEFAULT);
		GridLayout gridLayout = new GridLayout(1, false);
		gridLayout.horizontalSpacing = 0;
		gridLayout.verticalSpacing = 0;
		gridLayout.marginWidth = 0;
		gridLayout.marginHeight = 0;
		setLayout(gridLayout);

		Label lblSpacer = new Label(this, SWT.None);
		lblSpacer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1,
				1));
		lblSpacer.setVisible(false);

		lblMapName = new Label(this, SWT.NONE);
		lblMapName.setAlignment(SWT.CENTER);
		lblMapName.setForeground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
		lblMapName.setBackground(SWTResourceManager.getColor(SWT.COLOR_BLACK));
		lblMapName.setFont(SWTResourceManager.getFont("Tahoma", 12, SWT.BOLD));
		lblMapName.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true,
				false, 1, 1));
		lblMapName.setText("New Label");
	}

	public void setMapName(String string) {
		lblMapName.setText(string);
	}

	@Override
	protected void checkSubclass() {
		// Disable the check that prevents subclassing of SWT components
	}

	public void setBackgroundImage(Image image) {
		if (image != null && !image.isDisposed()) {
			bg = image;
			ar = (float) image.getBounds().height
					/ (float) image.getBounds().width;
			addControlListener(this);
			addPaintListener(this);
		}
	}

	@Override
	public void paintControl(PaintEvent e) {
		if (bg != null && !bg.isDisposed()) {
			Rectangle imageBounds = bg.getBounds();
			Rectangle clientArea = getBounds();
			e.gc.drawImage(bg, 0, 0, imageBounds.width, imageBounds.height, 0,
					0, clientArea.width, clientArea.height);
		}
	}

	@Override
	public void controlMoved(ControlEvent arg0) {
	}

	@Override
	public void controlResized(ControlEvent e) {
		updateMe();
	}
	
	public void updateMe() {
		griddata.widthHint = getBounds().width;
		griddata.heightHint = (int) ((float) getBounds().width * ar);
		griddata.minimumHeight = griddata.heightHint;
		setLayoutData(griddata);
		getParent().layout();
	}
}

was mache ich falsch??
 
Java:
setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
🙂

So gehts zumindest bei ScrollPanes..
 
was nir noch aufgefallen ist...
wenn ich
Java:
sc.setExpandVertical(true);
NICHT aufrufe, wird die scrollbar zwar korrekt angezeigt, aber die komponente drin nicht mehr... 🙁
 
Hab mal ein wenig rumprobiert. Aber das explizite Aufrufen von updateSC() oder layout() auf der MapsComposite führt dazu, dass der Inhalt anders gezeichnet wird, als bei einem Resize.
Das Problem ist, denke ich, dass deine MapComposites einen resize (aufgrund des Layouts der MapsComposite) erhalten, die MapsComposite selber aber nie resized oder layouted wird.
Die minimum height der Scrollbars wird also zu beginn inkorrekt gesetzt, weil die MapComposites noch gar nicht berechnet wurden.
Umgehen kann man das, indem du die MapComposites erzeugst bevor du die scrollpane und die composite (container) konfigurierst. Dann hast du aber den Effekt, den ich beschrieben habe, dass das Ergebnis anders ist, als bei einem resize
 
und wie kann ich das so lösen, dass ich zb die sc fülle, später dann wieder die children dispose und neue dafür adde...

das problem liegt ja darin dass ich die höhe der componente erst zur laufzeit berechne... also der sc keine fixe größe mitgeben kann...

sonnige grüße aus mexico 🙂
 
Krasses Problem^^
Ich weiß ehrlich gesagt auch nicht so recht, wie man das sinnvoll lösen kann 😉

Viel Spass in Mexiko und bleib im sicheren Gebiet 🙂
 

Neue Themen


Zurück
Oben