我创建了一个扩展 JEditorPane 的自定义类并使用它的 setPage() 方法。然而,我在使用它时遇到了一个非常奇怪的问题。这就是我的实现方式;
class WebReader extends JEditorPane {
WebReader(String addressIn) {
setEditable(false);
showPage(addressIn)
}
void showPage(String address) {
try {
setPage(address);
} catch (Exception e) {
e.printStackTrace();
}
}
调用可能看起来像这样;
WebReader fooReader = new WebReader("https://www.google.com");
fooReader.showPage("https://www.google.comxxxx");
这本不应该起作用,但神秘地却起作用了。
非常奇怪的是,如果我已经输入了正确的 URL,它就不会捕获错误的 URL。例如,如果我输入“https://www.google.com ”,它工作正常(应该如此),然后输入 https://www.google.comxxxxx ,它仍然在我的 JEditorPane 上显示 google.com 并且不会引发异常(我希望它这样做)。
值得注意的是,如果我输入https://www.google.comxxxxx作为我的“起始 URL”,它确实会引发异常。
编辑:添加了更多代码。
最佳答案
如果页面是异步加载的(在后台),您将不会收到 IOException。是否异步加载 URL 取决于 EditorKit 针对您正在加载的内容类型安装的文档。来自 documentation for JEditorPane.setPage :
This may load either synchronously or asynchronously depending upon the document returned by the
EditorKit
. If theDocument
is of typeAbstractDocument
and has a value returned byAbstractDocument.getAsynchronousLoadPriority
that is greater than or equal to zero, the page will be loaded on a separate thread using that priority.If the document is loaded synchronously, it will be filled in with the stream prior to being installed into the editor with a call to
setDocument
, which is bound and will fire a property change event. If anIOException
is thrown the partially loaded document will be discarded and neither the document or page property change events will be fired. If the document is successfully loaded and installed, a view will be built for it by the UI which will then be scrolled if necessary, and then the page property change event will be fired.If the document is loaded asynchronously, the document will be installed into the editor immediately using a call to
setDocument
which will fire a document property change event, then a thread will be created which will begin doing the actual loading. In this case, the page property change event will not be fired by the call to this method directly, but rather will be fired when the thread doing the loading has finished. It will also be fired on the event-dispatch thread. Since the calling thread can not throw anIOException
in the event of failure on the other thread, the page property change event will be fired when the other thread is done whether the load was successful or not.
显然,在这种情况下,网页的 EditorKit 是 HTMLEditorKit。来自 documentation of HTMLEditorKit :
Larger documents involve a lot of parsing and take some time to load. By default, this kit produces documents that will be loaded asynchronously if loaded using
JEditorPane.setPage
.
解决方法是自己同步加载文档,而不是使用 JEditorPane.setPage:
Document doc;
URLConnection connection = new URL(url).openConnection();
try (InputStream stream = connection.getInputStream()) {
String contentType = connection.getContentType();
EditorKit editorKit =
JEditorPane.createEditorKitForContentType(contentType);
doc = editorKit.createDefaultDocument();
editorKit.read(stream, doc, 0);
}
pane.setDocument(doc);
关于java - JEditorPane 的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43870900/