> I played with this code for a bit. There seem to be some problems with the way
> you use threads and arrange for stuff to happen on the AWT thread...
[me:]
> > I played with this code for a bit. There seem to be some problems with
> > the way you use threads and arrange for stuff to happen on the AWT
> > thread...
>
> Would you be good enough to enlighten me?
Oh, yes. Sorry. I wasn't trying to be coy, I just didn't think that criticism
(however constructively intended) would be all that welcome from a
non-expert -- especially when it didn't actually solve (or even help with) the
problem at hand.
Anyway, and in no special order...
There's no need to use invokeLater() in your button's action listener. You are
already on the right (AWT) thread.
In your search() method, you start threads for each URL. That means that you
end up doing AWT/Swing operations off the AWT thread -- which is illegal (or so
Sun have suddenly decided -- in preference to fixing their own bugs).
Oh, BTW, the code invoked from main() will also execute on a non-AWT thread,
which again is a no-no. But I assume that's just because this is only a simple
test rather than production code ;-) I didn't bother to change it either...
Those threads don't add anything anyway. The lengthy operation is downloading
data to populate the JEditorPane, and that happens in yet another thread
(stared internally by the implementation, as you are aware since you arrange
for that to happen explicitly).
Not really to do with threading, but there are several unnecessary (I think)
calls to revalidate().
The call to setAsynchronousLoadPriority() is unnecessary for two reasons. One
is that it happens /after/ the lengthy call of getCocument() and the call of
setPage() which is where it that property is used. The other is that the
Document already has an AsynchronousLoadPriority that will cause setPage() to
use a background thread to do the downloading.
I'll append my own modified version of your code. It's quite a lot simpler,
and works just as badly ;-) (I've moved some stuff around to suit my own
tastes better; I also removed the HyperlinkListener stuff just because it was
getting in my way and didn't help diagnose this /specific/ problem). The only
slight oddity (apart from the fact that it doesn't work) is that I use
invokeLater() to call the setPage() operation -- that allows the constructor to
return quickly and so the tabs list gets populated more-or-less immediately.
Oh, and I also changed some of the URLs since the HTML rendered was throwing
exceptions as it tried to handle their content.
Maybe there is a way to make this work smoothly, but I can't think of one. In
fact I can't see how it's possible since the HTML rendering /has/ to happen on
the AWT thread, but it's that which is (apparently) blocking input processing
for unacceptably long periods. I could be missing something, though.
-- chris
===========================
import java.net.URL;
import java.io.IOException;
import java.net.MalformedURLException;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.event.*;
import java.beans.*;
public class GuiFrame
extends JFrame
{
private JTabbedPane tabbedPane;
public GuiFrame()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
tabbedPane = new JTabbedPane();
tabbedPane.setPreferredSize(new Dimension(600,500));
add(tabbedPane, BorderLayout.CENTER);
JPanel northPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
add(northPanel, BorderLayout.NORTH);
JButton searchButton = new JButton("Load some pages");
searchButton.addActionListener(searchAction);
northPanel.add(searchButton);
pack();
setVisible(true);
}
private ActionListener searchAction
= new ActionListener()
{
public void
actionPerformed(ActionEvent evt)
{
search();
}
};
private URL[]
someUrls()
{
try
{
return new URL[]
{
new URL("http://java.sun.com"),
new URL("http://openp2p.com"),
new URL("http://www.slyck.com"),
new URL("http://p2p.weblogsinc.com"),
new URL("http://p2p-politics.org")
};
}
catch(MalformedURLException ex)
{
ex.printStackTrace();
return new URL[0];
}
}
private void
search()
{
tabbedPane.removeAll();
int idx = 0;
for (URL url : someUrls())
{
PageView view = new PageView(url);
tabbedPane.addTab(Integer.toString(++idx), view);
}
}
public static void
main(String[] args)
{
new GuiFrame();
}
}
class PageView
extends JPanel
{
private final JScrollPane scrollPane = new JScrollPane();
private final JEditorPane textComp = new JEditorPane();
PageView(final URL url)
{
setLayout(new BorderLayout());
add(scrollPane);
textComp.addPropertyChangeListener
(
new PropertyChangeListener()
{
public void
propertyChange(PropertyChangeEvent evt)
{
if (evt.getPropertyName().equals("page")
&& scrollPane.getViewport().getView() == null)
{
scrollPane.setViewportView(textComp);
}
}
}
);
textComp.setContentType("text/html");
// postpone setPage() so that the ctor can return without delay
SwingUtilities.invokeLater
(
new Runnable()
{
public void
run()
{
try
{
textComp.setPage(url);
}
catch(IOException ex)
{
ex.printStackTrace();
}
}
}
);
}
}
===========================
VisionSet - 22 Feb 2006 21:02 GMT
> Oh, yes. Sorry. I wasn't trying to be coy, I just didn't think that criticism
> (however constructively intended) would be all that welcome from a
> non-expert -- especially when it didn't actually solve (or even help with) the
> problem at hand.
Thanks for that Chris.
Mike W