Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Standard Widget Toolkit (SWT) » Force Browser Repaint
Force Browser Repaint [message #466824] Wed, 18 January 2006 00:47 Go to next message
Terry Corbet is currently offline Terry CorbetFriend
Messages: 14
Registered: July 2009
Junior Member
I am having trouble forcing the Browser Control
to repaint in a timely manner. A search of the archives
suggests that somewhat similar difficulties have been
reported, but I can not find a definitive answer to
what method of invocation will absolutely cause the
Browser to obey the general contract of Control.update(),
that is, to repaint immediately, causing all other
event loop processing to wait if necessary.

The overall application architecture may be responsible
for the fact that I only get 'delayed update', so let me
briefly lay that architecture out:

a. It is a standlaone SWT application.
b. Its primary Shell container layout is based
on CTabFolder.
c. In an individual tab, quite often a Browser
control is being used to render HTML either from
standard remote URL sites, from local files, or,
[as in the case that is failing] from dynamically-
generated HTML that is fed to the Browser via
setText().

This has all worked fine for over a year, even with
four or five concurrently-running Browser controls.

Now, however, the application is extending to
multiple views of some data model. In this case,
the primary view of the data model is rendered
via various widgets -- Label, Text, Button, etc. --
in a Composite on a Tab of CTabFolder. The
secondary view of the data model is rendered
as HTML in a separate, top-leel Shell containing a
Browser control.

There are circumstances under which multiple
changes to the data model will result in multiple
update requests to the views at a rate of about
one per second. While my debugging shows that the
events are all received and the invocation of
browser.update() is happening, no repaint occurs
until the loop which if firing the update requests
completes. [I've tried redraw() as well as
trying calling layout() on the Shell, but the
behavior does not change.]

The same events are being received and handled
immediately by the primary view -- constructed
only of 'other' SWT widgets. So, I've temporarily
added an 'other' SWT widget to the secondary view.
In that view there is now an update request to a Label
as well as an update request to the Browser.
The Label is handling the update and immediately
updating its part of the view, but the Browser
part of the secondary view only updates at the end.

I'm sorry for the long post, but I think it is
necessary to provide the precise information that
might lead to an answer. If I tried to create
a Snippet that displayed the MVC behavior with
multiple 'V's for a single 'M' and a single 'C',
it would be at least as long as the explanation.

The net, net is that update() on a standard widget
operates as expected, but an update() on a Browser
widget does not. At least one of the related postings
explored whether the 'rendering' of the Browser widget
occurs in the same thread as the repainting of
standard widgets. But that thread doesn't provide
a definitive answer to that question, nor, a guideline
as to how to proceed. If the Browser widget, because of
other requirements for its OLE behavior, cannot be
made to 'update-on-demand', there ought, at least,
to be some description of that fact somewhere in
the documentation.

Thank you.
Re: Force Browser Repaint [message #466846 is a reply to message #466824] Wed, 18 January 2006 05:13 Go to previous messageGo to next message
Daniel Spiewak is currently offline Daniel SpiewakFriend
Messages: 263
Registered: July 2009
Senior Member
Could you post your platform and swt version? Also, could you put together a smaller snippet with which perhaps you can reproduce the behavior? We appreciate your detailed explanation but it is difficult to understand what's really going on without code.

One more thing, have you tried your application on another platform to see if the behavior is replicated?
Re: Force Browser Repaint - posted by Terry Corbet [message #466859 is a reply to message #466846] Wed, 18 January 2006 14:50 Go to previous messageGo to next message
Daniel Spiewak is currently offline Daniel SpiewakFriend
Messages: 263
Registered: July 2009
Senior Member
Developing on Windows 2000.
The only other available test environment
is Windows XP. The application has
multiple Windows-only dependencies

SWT Version is 3.2.0 v3218.

Ok, it will take a couple of hours
to try to cull out the minimal code
to demonstrate the behavior.
Thanks for your reply, I'll try
to provide a snippet in the next
48 hours.
Re: Force Browser Repaint [message #466869 is a reply to message #466846] Wed, 18 January 2006 19:06 Go to previous messageGo to next message
Terry Corbet is currently offline Terry CorbetFriend
Messages: 14
Registered: July 2009
Junior Member
Daniel,

While this Snippet does not have the same
mechanisms for sending event notifications
between the participating components,
I think it does succinctly demonstrate
the failing behavior.

Thanks for whatever suggestion you can make.
Of course, I could replace the information
displayed as an HTML Table with SWT equivalent
constructions, but there are many, many cases
in which the rich client experience we want to
provide presents information that is rendered
by the embedded browser allowing the user
some 'presentational control' via easily-
understood and easily-manipulated Cascading
Style Sheets.

============================================================ =========
import java.util.*;

import org.eclipse.swt.*;
import org.eclipse.swt.browser.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

public class Snippet
{
private static final Random rand = new Random
(System.currentTimeMillis());
private static final String HTML =
("<html>" +
"<body style=\"overflow: hidden\">" +
"<table border=\"1\">" +
"<tr><td>%d</td><td>%d</td><td>%d</td></tr>" +
"<table>" +
"</body>" +
"</html>");

Display display;
Shell shell;
Label l1, l2, l3;
Browser browser;


public
Snippet()
{
display = new Display();
shell = new Shell (display);
shell.setLayout (new RowLayout (SWT.HORIZONTAL));
shell.setText ("Browser Update Snippet");

configure();

shell.setBounds (100, 100, 300, 300);
shell.pack();
shell.open();
while (! shell.isDisposed()) {
if (! display.readAndDispatch()) display.sleep();
}
display.dispose();
} // End of Constructor for Snippet.

private final
void
configure()
{
Composite left = new Composite (shell, SWT.BORDER);
left.setLayout (new RowLayout (SWT.HORIZONTAL));
l1 = new Label (left, SWT.BORDER);
l1.setSize (20, 20);
l1.setText ("0");
l2 = new Label (left, SWT.BORDER);
l2.setSize (20, 20);
l2.setText ("0");
l3 = new Label (left, SWT.BORDER);
l3.setSize (20, 20);
l3.setText ("0");

Composite center = new Composite (shell, SWT.BORDER);
center.setLayout (new FillLayout());
browser = new Browser (center, SWT.BORDER);
browser.setSize (100, 100);
browser.setText (String.format (HTML, 0, 0, 0));

Composite right = new Composite (shell, SWT.BORDER);
right.setLayout (new FillLayout());
Button button = new Button (right, SWT.BORDER);
button.setText ("Test Cycle");
button.addListener (SWT.Selection, new Listener()
{
public
void
handleEvent (Event evt)
{
for (int i = 0; i < 10; ++i) {
System.err.println ("Start of Cycle # " + (i + 1) +
".");

try {
Thread.sleep (1000);
} catch (Exception ignore) {;}

ennervate (
(rand.nextInt (8) + 1),
(rand.nextInt (8) + 1),
(rand.nextInt (8) + 1));

System.err.println ("End of Cycle # " + (i + 1) + ".");
} // End of Ennervation Simulation.
} // End of handleEvent().

}); // End of Anonymous Listener Class.
} // End of configure().

private final
void
ennervate (int i1, int i2, int i3)
{
l1.setText (Integer.toString (i1));
l1.update();
l2.setText (Integer.toString (i2));
l2.update();
l3.setText (Integer.toString (i3));
l3.update();

browser.setText (String.format (HTML, i1, i2, i3));
browser.update();
} // End of ennervate().

public static
void
main (String[] args)
{
Random rand = new Random (System.currentTimeMillis());

try {
Snippet snippet = new Snippet();
} catch (Exception ex) {
ex.printStackTrace();
}
} // End of main().

} // End of Snippet Class.

============================================================ ===============
Re: Force Browser Repaint [message #466903 is a reply to message #466869] Thu, 19 January 2006 02:52 Go to previous messageGo to next message
Daniel Spiewak is currently offline Daniel SpiewakFriend
Messages: 263
Registered: July 2009
Senior Member
Try Browser#refresh() instead of update(). I think that'll do the trick. I wrote a snippet to double check but I didn't have the time to do any in depth debugging. My preliminary results indicate that refresh() blocks until complete (at least on Windows, I can almost guarenty that it's different on a different platform).

Note, neither update() nor repaint() are overridden by Browser.
Re: Force Browser Repaint [message #466911 is a reply to message #466903] Thu, 19 January 2006 06:06 Go to previous messageGo to next message
Terry Corbet is currently offline Terry CorbetFriend
Messages: 14
Registered: July 2009
Junior Member
Daniel,

Thanks for your reply. Frankly, I doubt that
you can demonstrate any good results from an
invocation of browser.refresh(). I tried that
along with every other seemingly legitimate
alternative to browser.update() and was quite
surprised to find that the widget goes blank!
Since it is being rendered by IE, I can
right-click on the blank page and see the
Source -- it is <HTML></HTML>. I don't
belief refresh on content that is provided
via broswer.setText() knows what the semantics
of a refresh would mean in any case.

[I don't know the code, but I looked at inconsistencies
in the handling of setText() content versus setUrl()
content several times in the year that this application
has been evolving. The code behind setText() behaves
differently from the code behind setUrl() in several
important respects that end up being surprising since
it is not what is expected, or hoped for.]

So, since I believe that the problem of the updating of the
browser widget has to do with what thread is being used,
even though I can't explain it. Others have reported it.
So, here is a change to the snippet that works by causing
the update to the Label widget and the update to the
Browser widget both to be forced out of the event handling
thread into a separate thread. Then, the processing is
forced back into the user interface rendering thread by
the usual use of Display.syncExec(). As you can see by
running both versions, the first one leaves the browser
widget out of sync until the end of all updating; the
second one causes the two different 'views' to be properly
synchronized.

============================================================ ========
import java.util.*;

import org.eclipse.swt.*;
import org.eclipse.swt.browser.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

public class Snippet
{
static final Random rand = new Random (System.currentTimeMillis());
static final String HTML =
("<html>" +
"<body style=\"overflow: hidden\">" +
"<table border=\"1\">" +
"<tr><td>%d</td><td>%d</td><td>%d</td></tr>" +
"<table>" +
"</body>" +
"</html>");

Display display;
Shell shell;
Composite left, center, right;
Label l1, l2, l3;
Browser browser;


public
Snippet()
{
display = new Display();
shell = new Shell (display);
shell.setLayout (new RowLayout (SWT.HORIZONTAL));
shell.setText ("Browser Update Snippet");

configure();

shell.setBounds (100, 100, 300, 300);
shell.pack();
shell.open();
while (! shell.isDisposed()) {
if (! display.readAndDispatch()) display.sleep();
}
display.dispose();
} // End of Constructor for Snippet.

private final
void
configure()
{
left = new Composite (shell, SWT.BORDER);
left.setLayout (new RowLayout (SWT.HORIZONTAL));
l1 = new Label (left, SWT.BORDER);
l1.setSize (20, 20);
l1.setText ("0");
l2 = new Label (left, SWT.BORDER);
l2.setSize (20, 20);
l2.setText ("0");
l3 = new Label (left, SWT.BORDER);
l3.setSize (20, 20);
l3.setText ("0");

center = new Composite (shell, SWT.BORDER);
center.setLayout (new FillLayout());
browser = new Browser (center, SWT.BORDER);
browser.setSize (100, 100);
browser.setText (String.format (HTML, 0, 0, 0));

right = new Composite (shell, SWT.BORDER);
right.setLayout (new FillLayout());
Button button = new Button (right, SWT.BORDER);
button.setText ("Test Cycle");
button.addListener (SWT.Selection, new Listener()
{
public
void
handleEvent (Event evt)
{
System.err.println ("Entered Event Handler.");

/*
** Based on the belief that Browser updating
** is never executed in the 'User Interface Thread',
** let's get out of here as quickly as possible.
*/
Thread background = new Thread (new Runnable()
{
public final
void
run()
{
for (int i = 0; i < 10; ++i) {
System.err.println ("Start of Cycle # " + (i + 1) + ".");

try {
Thread.sleep (1000);
} catch (Exception ignore) {;}

ennervate (
(rand.nextInt (8) + 1),
(rand.nextInt (8) + 1),
(rand.nextInt (8) + 1));
System.err.println ("End of Cycle # " + (i + 1) + ".");
} // End of Ennervation Simulation.
} // End of run().
}); // End of Anonymous runnable Class.
background.start();

System.err.println ("Exited Event Handler.");
} // End of handleEvent().

}); // End of Anonymous Listener Class.
} // End of configure().

private final
void
ennervate (final int i1, final int i2, final int i3)
{
/*
** Since we are no longer being called
** in the 'UserInterfaceThread', this
** code now has to be sent back there.
*/
display.syncExec (new Runnable()
{
public final
void
run()
{
l1.setText (Integer.toString (i1));
l1.update();
l2.setText (Integer.toString (i2));
l2.update();
l3.setText (Integer.toString (i3));
l3.update();

browser.setText (String.format (HTML, i1, i2, i3));
} // End of run().
}); // End of Anonymous Runnable Class.
} // End of ennervate().

public static
void
main (String[] args)
{
Random rand = new Random (System.currentTimeMillis());

try {
Snippet snippet = new Snippet();
} catch (Exception ex) {
ex.printStackTrace();
}
} // End of main().

} // End of Snippet Class.

============================================================ ========
Re: Force Browser Repaint [message #466947 is a reply to message #466911] Thu, 19 January 2006 17:45 Go to previous messageGo to next message
Daniel Spiewak is currently offline Daniel SpiewakFriend
Messages: 263
Registered: July 2009
Senior Member
Your thread hack sounds like a good way to fix the problem. I would bet that the undesirable update() behavior has something to do with the event based nature of the Windows repaint loop. However, that's just a guess. Sorry I couldn't be more helpful.
Re: Force Browser Repaint [message #466958 is a reply to message #466947] Fri, 20 January 2006 01:53 Go to previous message
Terry Corbet is currently offline Terry CorbetFriend
Messages: 14
Registered: July 2009
Junior Member
Actually, thanks for helping me think through
the issues and forcing me to document the
behaviors. I have opened a Bug in the hopes
that, at a minimum, the information concerning
these behaviors will be validated and highlighted
in the documentation so that you won't ahve to
spend valuable time responding to such queries.
Previous Topic:Hiding controls
Next Topic:How to get flashing on OS task bar work?
Goto Forum:
  


Current Time: Fri Dec 27 01:39:47 GMT 2024

Powered by FUDForum. Page generated in 0.03132 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top