2017-06-14 117 views
1

我正在开发基于Java的网页抓取工具。我创建了一个JFrame(Java:Swing)。我的抓取工具正在成功运行。它正在访问创建的链接。但我想在JTextArea中动态地添加爬行链接,但它不会。我不能这样做。当我尝试这个时,我的程序是freezen。但我可以设置访问的网址到控制台。使用Java Swing进行网页抓取

我的GUI这样的:

image

我的代码行是这样的:

Document html = null; 

    try { 
     html = Jsoup.connect(url).get(); 
     Elements links = html.select("a"); 

     for(Element link: links) { 
      String tmp = link.attr("abs:href"); 
      jTextArea2.append(tmp + "\n"); 

      if(!this.visitedUrl.contains(tmp)) { 
       this.foundedUrl.add(tmp); 
       System.out.println(tmp); 
      } 
     } 

     while(this.foundedUrl.size() > 0) { 
      String tmp = this.foundedUrl.get(this.foundedUrl.size() - 1); 
      this.foundedUrl.remove(this.foundedUrl.size() - 1); 
      if(!this.visitedUrl.contains(tmp)) { 
       this.linkTracker(tmp); 
      } 
     } 

我怎么能在JTextArea中集访问的URL动态?

+0

您是否从UI事件线程调用此代码?大多数Swing控件支持仅从UI事件线程调用。 –

+0

欢迎来到堆栈溢出,请参加[导览],并通过[帮助],这会引导你[问],这会稍后告诉你发布一个有效的[mcve]来证明你的问题。因为你的程序是不完整的,因此不可编译,我们不希望你的整个应用程序,但一个简单但完整的例子(而不是代码片段),可以证明你的问题。例如,您可以对URL进行硬编码,并有一个启动该过程的'JTextArea'和'JButton'。我们知道你的图形用户界面冻结了,但你的问题太广泛了,因为它缺乏足够的信息(即MCVE)需要回复... – Frakcool

+0

...因为你可能没有在EDT中初始化你的应用程序,或者你正在运行在美国东部时间,也许你想看看[Swing Worker](https://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html),这可以让你处理长期任务单独的线程和不阻止EDT(冻结您的GUI)。另请阅读[并发中的Swing](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/) – Frakcool

回答

0

试试这个:

new Thread((Runnable)() -> 
{ 
    Document html = null; 

    try { 
    html = Jsoup.connect(url).get(); 
    Elements links = html.select("a"); 

    for(Element link: links) { 
     String tmp = link.attr("abs:href"); 
     EventQueue.invokeLater(() -> { 
      jTextArea2.append(tmp + "\n"); 
     }); 

     if(!this.visitedUrl.contains(tmp)) { 
      this.foundedUrl.add(tmp); 
      System.out.println(tmp); 
     } 
    } 

    while(this.foundedUrl.size() > 0) { 
     String tmp = this.foundedUrl.get(this.foundedUrl.size() - 1); 
     this.foundedUrl.remove(this.foundedUrl.size() - 1); 
     if(!this.visitedUrl.contains(tmp)) { 
      this.linkTracker(tmp); 
     } 
    } 
    }catch(Exception e){} 
}).start(); 

你GUI被冻结的原因是因为你是阻塞GUI线程。因此,通过创建一个新的线程并从那里运行,在不同的线程上启动您的操作。 然后获取更新调用EventQue 它会告诉GUI线程将文本添加到JTextArea