在另一个线程中使用swing

时间:2017-02-14 08:32:07

标签: java multithreading swing

我正在使用Java开发基于cli的自定义Web爬网程序。由于它需要一个用户友好的图形界面来显示结果,我应该添加一个涉及一些树,标签,表等的摇摆框架。 该图形界面是其中一个开关,必须在用户调用它时启动。因此,我必须在一个新线程中启动此接口,以便应用程序可以继续执行其他任务并在需要时更新GUI框架内的组件。 我的GUI类是这样的:

public class Frame extends JFrame {
   ......
   public static JLabel urlLabel;
   ......
   public static void run() {
      urlLabel = new JLabel();
      urlLabel.setText("Test Url");
      SwingUtilities.invokeLater(new Runnable() {
          public void run() {
              new Frame().setVisible(true);
          }
      });
   }
   .....
 }

而且,我把它从我的主类中分叉出来:

.....
if(cmd.gui){
   Frame.run();
   Frame.urlLabel.setText("New Url");
 }
......

不幸的是,标签的文字并没有改变。我已经测试了repaint()revalidate()以及其他类似的功能,但是没有出现任何问题。 我测试getText()以确保可以从主类访问urlLabel,并且它有效(我可以检索标签文本)。

我想知道如何解决这个问题? (基本上,我需要在不同的线程中启动一个swing框架并从主线程控制其组件)

提前致谢。

2 个答案:

答案 0 :(得分:0)

如果使用invokeLater(),则在此线程中的当前操作完成后,将在EventThread中启动Runnable。如果您的标签未更新,则可能是您的EventThread正忙着做其他事情 - 例如爬网。

你肯定需要确保你的爬行工作是在另一个线程中完成的(启动一个新的,不要使用任何运行的线程,因为这很可能是EventThread)。然后,您可以在此其他线程中使用invokeLater()来更改EventThread中的标签。

提示:您可以使用SwingUtilities.isEventDispatchThread()检查您是否在EventThread中。

请记住,您的数据/模型将被不同的线程使用,并且当您的GUI尝试显示数据时,这可能会在您的工作线程中更改数据时出现问题。

答案 1 :(得分:0)

谢谢你们的帮助。 最后,我可以通过使用SwingUtilities.invokeLater来更新标签的文本来克服这个障碍。 我在这里提到了这种方法,因为其他人可能需要它:

主要班级:

public class Frame extends JFrame {
......
  private static JLabel urlLabel;
......
  public JLabel getU(){
    return urlLabel;
  }
  public static void run() {
  urlLabel = new JLabel();
  urlLabel.setText("Test Url");
  SwingUtilities.invokeLater(new Runnable() {
      public void run() {
          new Frame().setVisible(true);
      }
  });
 }
  .....
}

GUI类:

if(cmd.gui){
     Frame().run();
     SwingUtilities.invokeLater( new Runnable() {
          @Override
          public void run() {
                 gui.getU().setText("New Url");
          }
     });
}
.....

关于这种方式的问题: 由于我需要在抓取过程中多次更新一些标签和树节点,想知道为每个标签和树节点启动新的Runnable是否会超载?如果是,我该如何管理?

<强> --- --- UPDATE

根据@ xander的评论,可以使用lambda而不是Runnable。我认为lambda没有像新对象那样过载。