Java关于JDialog的问题

te_ar 2020-07-21 08:05:41
正在写一个爬虫程序,然后因为爬取数据需要时间,所以就想在爬取的时候增加一个进度条来表示正在爬取。于是创建了一个Probar类,当开始爬取数据时,new Probar()来显示进度条,表示正在爬取数据,同时显示消息日志来说明哪些数据爬到了,哪些没有,当爬取完数据之后,就关闭Probar。

主JFrame中相关代码:

/**** 准备开始爬取数据 ***/
Probar probar=new Probar(this);//这里this是作为parentComponent传入
new Thread(probar).start();
下面爬取数据,当爬取完数据时:
probar.setCanRun(false);

Probar类,表示进度条

public class Probar extends JDialog implements Runnable{
private boolean canRun=true;
private JLabel jl1=new JLabel("正在加载中,请稍后");
private JProgressBar pb=new JProgressBar(JProgressBar.HORIZONTAL);//进度条
private JLabel lbLog=new JLabel("消息日志");
private JTextArea taLog=new JTextArea();
private JScrollPane spLog=new JScrollPane(taLog);
public Probar(Component parentComponent){
super((JFrame) parentComponent);
this.setSize(800,650);
this.setLayout(null);

jl1.setSize(150,70);
jl1.setLocation(340,0);
jl1.setFont(new Font("黑体",Font.BOLD,24));
this.add(jl1);

pb.setLocation(100,70);
pb.setSize(600,15);
pb.setBorderPainted(true);
pb.setIndeterminate(true);
pb.setVisible(true);
this.add(pb);

lbLog.setLocation(47,75);
lbLog.setSize(120,70);
lbLog.setFont(new Font("黑体",Font.PLAIN,20));
this.add(lbLog);

taLog.setFont(new Font("微软雅黑",Font.PLAIN,18));
taLog.setEnabled(false);
spLog.setLocation(50,123);
spLog.setSize(680,450);
this.add(spLog);

this.setVisible(true);
GUIUtil.toCenter(this);

}

public void setCanRun(boolean canRun) {
this.canRun = canRun;
}

public void insertLog(String msg){
taLog.append(msg+"\n");
}


@Override
public void run() {
while(canRun) {
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
JOptionPane.showMessageDialog(this,"爬取完成");
this.dispose();
}

public static void main(String[] args) {
new Probar(null);
}

}


不知道为什么这个JDialog每次只有爬取完数据,也就是运行到JOptionPane.showMessageDialog(this,"爬取完成");才会显示出来,有什么办法可以让这个ProBar类可以立即显示出来?
...全文
1879 6 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
sunyiz 2020-07-22
  • 打赏
  • 举报
回复
引用 4 楼 te_ar 的回复:
在new Thread(probar).start(); 到 probar.setCanRun(false);之间还有一段代码用来执行爬取网页的html源码和提取图片,这个可能会比较耗时,所以我添加了一个JProgressbar来表示进度。

详细是这样的


你的这段代码是在哪里执行的?
一个ActionListener里吗?
或者别的什么Listener里面?

如果是的话,那么就是违反了Swing的一个基本规范:
耗时代码不可在EDT(事件指派线程)中执行
这样会阻碍UI的正常刷新

你应该把这些耗时代码放到另一个单独线程中去做
(包括最后那句 probar.setCanRun(false);)
te_ar 2020-07-22
  • 打赏
  • 举报
回复
引用 2 楼 sunyiz 的回复:
你这段测试代码从 JDialog显示出来到 JOptionPane 显示弹出对话框之间实际上只有20毫秒延时 如果就这样运行,看起来肯定是一起出来的 还有一点 new Thread(probar).start(); 到 probar.setCanRun(false); 之间无延时 这样很可能你的 Thread 的 run 中的 while 还没有被执行到,canRun已经是 false 了 你可以这样试试: 1、把 run 方法中那个模拟爬虫任务的延时增加一些,比如延时2000 2、在 new Thread(probar).start(); 和 probar.setCanRun(false); 之间加个sleep 这个 sleep 可以很短,1、2毫秒就够了
在new Thread(probar).start(); 到 probar.setCanRun(false);之间还有一段代码用来执行爬取网页的html源码和提取图片,这个可能会比较耗时,所以我添加了一个JProgressbar来表示进度。 详细是这样的

            Probar probar=new Probar(this);
            new Thread(probar).start();
            /***** 下面开始代码适用于爬取数据 *****/
            Webs.clear();
            Sensitives.clear();
            htmls.clear();
            results.clear();

            String[] webs=tfWebsite.getText().split(";");
            Webs.addAll(Arrays.asList(webs));
            String[] senstives=tfSenstive.getText().split(";");
            Sensitives.addAll(Arrays.asList(senstives));
            for(String web:webs){
                //爬取html源码和Img
                String html=Crawler.crawler("https://"+web);
                htmls.add("*** "+web+" ***\n"+html+"\n");
                results.add("*** "+web+" ***\n"+Crawler.analysis(html)+"\n");
                probar.insertLog(web+" html源码爬取完成");
                Crawler.crawlerImg(html,probar);
            }
            /**** 爬取数据结束 ****/
            probar.setCanRun(false);
            showByHtml();
te_ar 2020-07-22
  • 打赏
  • 举报
回复
引用 1 楼 wangdong20 的回复:
在Probar构造方法里面最后面添加这一句试试JOptionPane.showMessageDialog(this,"****");
最后加了JOptionPane.showMessageDialog(this,"****");之后,JDialog会显示出来,但是之后进度条JProgressBar会卡住不动了,直到canRun置为false进度条才会继续动。
sunyiz 2020-07-22
  • 打赏
  • 举报
回复
你这段测试代码从 JDialog显示出来到 JOptionPane 显示弹出对话框之间实际上只有20毫秒延时
如果就这样运行,看起来肯定是一起出来的

还有一点 new Thread(probar).start(); 到 probar.setCanRun(false); 之间无延时
这样很可能你的 Thread 的 run 中的 while 还没有被执行到,canRun已经是 false 了

你可以这样试试:
1、把 run 方法中那个模拟爬虫任务的延时增加一些,比如延时2000
2、在 new Thread(probar).start(); 和 probar.setCanRun(false); 之间加个sleep 这个 sleep 可以很短,1、2毫秒就够了
wangdong20 2020-07-22
  • 打赏
  • 举报
回复
在Probar构造方法里面最后面添加这一句试试JOptionPane.showMessageDialog(this,"****");
te_ar 2020-07-22
  • 打赏
  • 举报
回复
引用 5 楼 sunyiz 的回复:
[quote=引用 4 楼 te_ar 的回复:] 在new Thread(probar).start(); 到 probar.setCanRun(false);之间还有一段代码用来执行爬取网页的html源码和提取图片,这个可能会比较耗时,所以我添加了一个JProgressbar来表示进度。 详细是这样的
你的这段代码是在哪里执行的? 一个ActionListener里吗? 或者别的什么Listener里面? 如果是的话,那么就是违反了Swing的一个基本规范: 耗时代码不可在EDT(事件指派线程)中执行 这样会阻碍UI的正常刷新 你应该把这些耗时代码放到另一个单独线程中去做 (包括最后那句 probar.setCanRun(false);)[/quote] 谢谢!

62,635

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧