我正在使用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框架并从主线程控制其组件)
提前致谢。
答案 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没有像新对象那样过载。