Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 321328 - no update of screen on change of widget
Summary: no update of screen on change of widget
Status: RESOLVED NOT_ECLIPSE
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 4.0   Edit
Hardware: PC Windows 2000
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Platform-SWT-Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-07-30 08:05 EDT by jo CLA
Modified: 2010-07-30 10:43 EDT (History)
1 user (show)

See Also:


Attachments
Screenshots with visible/invisible label (5.79 KB, image/png)
2010-07-30 08:21 EDT, jo CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description jo CLA 2010-07-30 08:05:52 EDT
Build Identifier: MyEclipse 6.0.1-GA-200710 (but is also with compiled jar, so not connected to build)

I dispose of a label, create a new label.
The new label stays invisible as long as the Shell area doesn't change.
The button "useless" is trying several maneuvers to force a real redraw, but fails. The button "pixeltrick" changes the shell area 1 pixel, and with that trick manages to force a redraw.
swt library is swt-3.5.2-win32-win32-x86.


Reproducible: Always

Steps to Reproduce:
package auge;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;

public class RefreshBug {
	static Label label;

	public static void main(String[] args) {
		final Display display = new Display ();
		final Shell testshell = new Shell(display, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
		final GridLayout gridLayout = new GridLayout();
		gridLayout.numColumns = 1;
		gridLayout.marginBottom = 0;
		testshell.setLayout(gridLayout);

		final Button update = new Button (testshell, SWT.PUSH);
		update.setText ("&Update");
		update.addSelectionListener (new SelectionAdapter () {
			public void widgetSelected (SelectionEvent e) {
				label.dispose();
				label = new Label (testshell, SWT.NONE | SWT.BORDER);
				label.setText ("I'm invisible");
				testshell.pack();
				testshell.open();
			}
		});

		final Button useless = new Button (testshell, SWT.PUSH);
		useless.setText ("&Notworking");
		useless.addSelectionListener (new SelectionAdapter () {
			public void widgetSelected (SelectionEvent e) {
				testshell.changed(testshell.getChildren());
				testshell.redraw();
				testshell.setModified(true);
				testshell.setRedraw(true);
				testshell.update();
				testshell.pack(true);
				testshell.open();
			}
		});
		
		final Button trick = new Button (testshell, SWT.PUSH);
		trick.setText ("&Pixeltrick");
		trick.addSelectionListener (new SelectionAdapter () {
			public void widgetSelected (SelectionEvent e) {
				if (gridLayout.marginBottom == 0) gridLayout.marginBottom = 1;
				else gridLayout.marginBottom = 0;
				testshell.setLayout(gridLayout);
				testshell.pack();
				testshell.open();
			}
		});
		
		label = new Label (testshell, SWT.NONE | SWT.BORDER);
		label.setText ("I'm visible");

		testshell.pack();
		testshell.open();
	    while (!testshell.isDisposed()) {
	    	if (!display.readAndDispatch()) display.sleep();
	    }
	    display.dispose();
	}

}
Comment 1 jo CLA 2010-07-30 08:21:11 EDT
Created attachment 175561 [details]
Screenshots with visible/invisible label

You see first a screenshot of the freshly started application. After the "update"-Button, which deletes and creates a label, the new label is invisible.
It stays invisible even after all the operations triggered via the "Notworking"-Button. Finally, a press on the "Pixeltrick"-Button makes the label visible.
Comment 2 Lakshmi P Shanmugam CLA 2010-07-30 08:41:27 EDT
The shell is using a layout. So for the newly created label you should call testshell.layout() so that the size and location of the label can be set.
Comment 3 jo CLA 2010-07-30 08:45:37 EDT
The behaviour was identical with swt-3.6-win32-win32-x86.
Comment 4 Felipe Heidrich CLA 2010-07-30 08:58:52 EDT
This is the right code:
 final Button update = new Button (testshell, SWT.PUSH);
        update.setText ("&Update");
        update.addSelectionListener (new SelectionAdapter () {
            public void widgetSelected (SelectionEvent e) {
                label.dispose();
                label = new Label (testshell, SWT.NONE | SWT.BORDER);
                label.setText ("I'm invisible");
                label.getParent().layout();
//                testshell.pack();
//                testshell.open();
            }
        });

Closing as not Eclipse.
Comment 5 jo CLA 2010-07-30 09:15:44 EDT
(In reply to comment #4)

That does in fact work. It causes a much "bigger" redraw though (flashing of
whole shell area) than the pixel change...

Also it's said about layout():
"You would do this after changing anything about the children that might affect
their size or position"
(http://www.eclipse.org/articles/article.php?file=Article-Understanding-Layouts/index.html)
But in fact it only seems to be needed if size or position are *not* affected.
If you change size or position (eg by giving the label a longer text) the
redraw (and a much more economic one, no window flashing) *does* occur and the
new label is visible.

Also it's said (same place): "Note that shell.open() causes a layout to occur"
which seems to be untrue (I do a shell.open() in the Update and Nonworking
button event).

While I accept the solution via layout(), I still feel the "softer" redraw
which can be achieved with the pixel trick or otherwise triggering a minimal
resize should be available *somehow* here.

Also, I have an application with similar function where layout() does not suffice. I'll try to whittle it down to the relevant portions.

But I gleaned from your comment, the close of this bug is due to "not being eclipse"... if this is only about eclipse, then I'm indeed wrong here, and sorry. I was under the impression this bugzilla treated swt bugs as well.
Comment 6 Felipe Heidrich CLA 2010-07-30 10:43:42 EDT
(In reply to comment #5)
> (In reply to comment #4)
> That does in fact work. It causes a much "bigger" redraw though (flashing of
> whole shell area) than the pixel change...

Yes, See Bug 103863
You can use "label.getParent().layout(new Control[] {label}, SWT.DEFER);" instead. 

> Also it's said about layout():
> "You would do this after changing anything about the children that might affect
> their size or position"
> (http://www.eclipse.org/articles/article.php?file=Article-Understanding-Layouts/index.html)
> But in fact it only seems to be needed if size or position are *not* affected.

No, the article is correct.

> If you change size or position (eg by giving the label a longer text) the
> redraw (and a much more economic one, no window flashing) *does* occur and the
> new label is visible.

Yes, the redraw does occur (for free). But the *layout* does not occur (for free). You need to call layout yourself.

Your code failed not because you missed a redraw, the label was invisible because its size is 0,0 (size was never set in it). Calling layout in the parent container causes the layout manager to recalculate the size for the child.

> Also it's said (same place): "Note that shell.open() causes a layout to occur"
> which seems to be untrue (I do a shell.open() in the Update and Nonworking
> button event).

If you never set the size of the shell the first shell.open() will cause a resize, which will cause a layout to happen.
For example:
1:
shell.open();//send resize (size == preferred size)

2:
shell.setSize(400, 400); //send resize (size == 400, 400)
shell.open(); // does _not_ send resize

3:
shell.open();//send resize (size == preferred size)
shell.open(); // does _not_ send resize


> While I accept the solution via layout(), I still feel the "softer" redraw
> which can be achieved with the pixel trick or otherwise triggering a minimal
> resize should be available *somehow* here.

And it is:  "label.getParent().layout(new Control[] {label}, SWT.DEFER);" 

> Also, I have an application with similar function where layout() does not
> suffice. I'll try to whittle it down to the relevant portions.
> But I gleaned from your comment, the close of this bug is due to "not being
> eclipse"... if this is only about eclipse, then I'm indeed wrong here, and
> sorry. I was under the impression this bugzilla treated swt bugs as well.

You got it right, it treated swt bugs.

I close it as not eclipse because the bugs is not in Eclipse (which SWT is part), the bug is in application code: you forgot to call parent.layout() after changing its children, that is all.