Home » Eclipse Projects » Standard Widget Toolkit (SWT) » Force Browser Repaint
Force Browser Repaint [message #466824] |
Wed, 18 January 2006 00:47 |
Terry Corbet 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 #466869 is a reply to message #466846] |
Wed, 18 January 2006 19:06 |
Terry Corbet 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 #466911 is a reply to message #466903] |
Thu, 19 January 2006 06:06 |
Terry Corbet 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.
============================================================ ========
|
|
| | |
Goto Forum:
Current Time: Sun Dec 08 15:45:18 GMT 2024
Powered by FUDForum. Page generated in 0.28397 seconds
|