JEdi​​torPane的奇怪行为

时间:2017-05-09 13:15:13

标签: java swing url jeditorpane

我已经创建了一个自定义类,它扩展了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作为我的'起始网址',它确实会引发异常。

编辑:添加了更多代码。

2 个答案:

答案 0 :(得分:2)

如果页面异步加载(在后台),则不会出现IOException。是否异步加载URL取决于EditorKit为要加载的内容类型安装的文档。来自documentation for JEditorPane.setPage

  

这可以同步或异步加载,具体取决于EditorKit返回的文档。如果Document的类型为AbstractDocument并且AbstractDocument.getAsynchronousLoadPriority返回的值大于或等于零,则该页面将使用该优先级加载到单独的线程上。

     

如果文档是同步加载的,那么在通过调用setDocument安装到编辑器之前,它将被流填充,该IOException被绑定并将触发属性更改事件。如果抛出setDocument,则将丢弃部分加载的文档,并且不会触发文档或页面属性更改事件。如果文档已成功加载并安装,UI将为其构建一个视图,然后在必要时滚动它,然后将触发页面属性更改事件。

     

如果文档是异步加载的,文档将立即通过调用IOException安装到编辑器中,这将调用文档属性更改事件,然后将创建一个将开始执行实际加载的线程。在这种情况下,直接调用此方法不会触发页面属性更改事件,而是在执行加载的线程完成时触发。它也将在事件派发线程上触发。由于调用线程在另一个线程发生故障时无法抛出JEditorPane.setPage,因此当另一个线程完成时,无论加载是否成功,都会触发页面属性更改事件。

显然,在这种情况下,网页的EditorKit是一个HTMLEditorKit。来自documentation of HTMLEditorKit

  

较大的文档涉及大量解析并需要一些时间来加载。默认情况下,如果使用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); 加载,此工具包将生成将异步加载的文档。

解决方法是自己同步加载文档,而不是使用JEditorPane.setPage:

componentWillReceiveProps() {
 realms = this.state.realm;

if(realms == ""){
  src = [];
}
else{
  src =  this.state.realm.objects('Bills');
}

this.setState({
  dataSource: this.state.dataSource.cloneWithRows(src)
})
}

答案 1 :(得分:1)

我设法解决了!

我在showPage()中添加了以下内容:

setEditorKit(createDefaultEditorKit()); 

因此,每次更改网页时,它都会创建一个新的EditorKit。