Java swing 进度条的显示问题

liaijin2009 2010-11-21 07:03:03
最近在做一个C/S的通行软件,其中涉及到文件传输的功能,希望能够显示文件的上传进度,但是遇到一些问题无法解决:
当传输文件时,进度条必须不断更新,但是Swing好像是单线程的,而且对Swing界面的更改不能在其他线程中进行(如果有错请指教),结果我现在的问题就是文件传输的过程中进度条不能更新,而且整个界面被阻塞,导致对界面无法进行其他操作,只有文件传输完成后才突然显示100%,下面贴出部分代码:

包含进度条的类:
public class TransmitBar extends JPanel{
private File file;
private JProgressBar progressBar;
public TransmitBar(File file){
this.file=file;
progressBar=new JProgressBar(0, (int)file.length());
progressBar.setStringPainted(true);
progressBar.setValue(0);
progressBar.setPreferredSize(new Dimension(215,20));

this.setLayout(null);
progressBar.setBounds(0,0,215,15);
this.add(progressBar);
this.setPreferredSize(new Dimension(215,15));
}
public TransmitBar getObj(){
return this;
}
public void start(){
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try{
FileInputStream fis=new FileInputStream(file);
FileOutputStream fos=new FileOutputStream("D:\\"+file.getName());
int data;
int i=0;
while((data=fis.read())!=-1){
fos.write(data);
i++;
progressBar.setValue(i);
//getObj().repaint();
//getObj().updateUI();
}
//Thread.interrupted();
}catch(Exception e){

}
}
});
}
}

主窗体中通过按钮激发文件选择,将选择的文件传入上面类的构造方法中,然后调用类的start()方法,现在文件可以传输,但是进度条无法更新:
...全文
703 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
diggywang 2010-11-24
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 asliuyajun 的回复:]

这个可以算的 。。。。
但swing也可以多线程啊 !!
[/Quote]

Swing的多线程和其他服务器程序的多线程还是有些差别的,Swing在考虑多线程的同时还要注意界面变化和更新,这些都是要在EDT线程中去实现的。
风影萧诺 2010-11-23
  • 打赏
  • 举报
回复
这个可以算的 。。。。
但swing也可以多线程啊 !!
dp5251506 2010-11-23
  • 打赏
  • 举报
回复
本人新手学习学习!
diggywang 2010-11-23
  • 打赏
  • 举报
回复
除了SwingWorker,其他Thread实现都是不安全的
sam012 2010-11-22
  • 打赏
  • 举报
回复
帮定, 祝你好运
爱摸鱼de老邪 2010-11-22
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 huntor 的回复:]

14. 32. 14. SwingWorker and ProgressBar
[/Quote]
顶这个。将上传的逻辑处理放在doInBackground方法中,在publish方法中可以更新你的JProgressBar组件,详见API中的SwingWoker说明。
tian_jie 2010-11-22
  • 打赏
  • 举报
回复
你把更新界面的代码放在
SwingUtilities.invokeLater(new Runnable(){
public void run(){
processBar.setValue(i); }
});
不要把IO相关的操作放到界面更新队列里面去
  • 打赏
  • 举报
回复
还是用swingworker 比较好,很不错
xtkhnje888 2010-11-22
  • 打赏
  • 举报
回复
新手想看看
huntor 2010-11-21
  • 打赏
  • 举报
回复
sunyiz 2010-11-21
  • 打赏
  • 举报
回复
原来还用了 substance 啊,这个真的不好说了
这个LookAndFeel还要用一个单独的线程来启动才行
它用线程实现了一些减隐,渐变的特效,也用HighLighter实现了不少效果
但是相对的,Swing本身的对UI进行改变的很多方法都会被Substance的效果所覆盖
HighLighter也完全失效,
也就是说,如果你用了Substance就要完全接受它的一切,除非你能自己修改它的核心代码

我以前也试过这个LookAndFeel,
但是我发现它把我很多自己优化界面的东西覆盖掉了,只能放弃
约翰羊 2010-11-21
  • 打赏
  • 举报
回复
哟,这个还真不知道了。
帮你UP
liaijin2009 2010-11-21
  • 打赏
  • 举报
回复
还是不行,我把start()方法改成如下:
public void start(){
Thread thread = new Thread(new Runnable() {
public void run() {
try{
FileInputStream fis=new FileInputStream(file);
FileOutputStream fos=new FileOutputStream("D:\\"+file.getName());
int data;
int i=0;
while((data=fis.read())!=-1){
fos.write(data);
i++;
progressBar.setValue(i); getObj().repaint();
getObj().updateUI();
}

}catch(Exception e){

}
}
});
thread.start();
}

结构出现异常(我使用了Substance来美化界面):
org.jvnet.substance.api.UiThreadingViolationException: Component state change must be done on Event Dispatch Thread
at org.jvnet.substance.utils.SubstanceCoreUtilities.testComponentStateChangeThreadingViolation(SubstanceCoreUtilities.java:2386)
at org.jvnet.substance.SubstanceProgressBarUI$1.stateChanged(SubstanceProgressBarUI.java:156)
at javax.swing.DefaultBoundedRangeModel.fireStateChanged(Unknown Source)
at javax.swing.DefaultBoundedRangeModel.setRangeProperties(Unknown Source)
at javax.swing.DefaultBoundedRangeModel.setValue(Unknown Source)
at javax.swing.JProgressBar.setValue(Unknown Source)
at client.ui.file.TransmitBar$1.run(TransmitBar.java:85)
at java.lang.Thread.run(Unknown Source)
错误就是progressBar.setValue(i);这一句,在网上看到这样一句话:Swing界面的更改不能在其他线程中进行,不知道是不是这个原因
liaijin2009 2010-11-21
  • 打赏
  • 举报
回复
还是不行,我把start()方法改成如下:
public void start(){
Thread thread = new Thread(new Runnable() {
public void run() {
try{
FileInputStream fis=new FileInputStream(file);
FileOutputStream fos=new FileOutputStream("D:\\"+file.getName());
int data;
int i=0;
while((data=fis.read())!=-1){
fos.write(data);
i++;
progressBar.setValue(i); getObj().repaint();
getObj().updateUI();
}

}catch(Exception e){

}
}
});
thread.start();
}

结构出现异常(我使用了Substance来美化界面):
org.jvnet.substance.api.UiThreadingViolationException: Component state change must be done on Event Dispatch Thread
at org.jvnet.substance.utils.SubstanceCoreUtilities.testComponentStateChangeThreadingViolation(SubstanceCoreUtilities.java:2386)
at org.jvnet.substance.SubstanceProgressBarUI$1.stateChanged(SubstanceProgressBarUI.java:156)
at javax.swing.DefaultBoundedRangeModel.fireStateChanged(Unknown Source)
at javax.swing.DefaultBoundedRangeModel.setRangeProperties(Unknown Source)
at javax.swing.DefaultBoundedRangeModel.setValue(Unknown Source)
at javax.swing.JProgressBar.setValue(Unknown Source)
at client.ui.file.TransmitBar$1.run(TransmitBar.java:85)
at java.lang.Thread.run(Unknown Source)
错误就是progressBar.setValue(i);这一句,在网上看到这样一句话:Swing界面的更改不能在其他线程中进行,不知道是不是这个原因
约翰羊 2010-11-21
  • 打赏
  • 举报
回复
我一直这么用。

Thread thread = new Thread(new Runnable() {
public void run() {
for(int pos=0;pos<100;pos++){
jProgressBar1.setValue(pos);
}
}
});
thread.start();
huntor 2010-11-21
  • 打赏
  • 举报
回复
使用 SwingWorker 。
具体用法请 google

62,615

社区成员

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

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