最近在做一个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()方法,现在文件可以传输,但是进度条无法更新:
当传输文件时,进度条必须不断更新,但是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()方法,现在文件可以传输,但是进度条无法更新:
解决方案 »
- Process对象如何判断该进程已经结束?
- oracle数据库插入数据后 数据内容跟插入的不同
- 关于JAVA生成可执行文件JAR的问题,我的JAR文件怎么使用已经打包好的其他.jar文件!
- jbuilder8编辑代码时,光标位置经常显示不正常,如何改正?
- 关于在JButton上处理鼠标事件的问题
- 浏览器的两个不同窗口传递参数
- 求JAVA程序员
- 存储过程执行错误: 对只转发结果集的无效操作?解决后定送100分。
- 高分求助!!!
- 请问各位朋友,Java程序中如何保存数据到Oracle表里并调用他们!!!
- HttpURLConnection cookie 问题,帮忙看一下
- 谁发我个head first Java中文清晰版pdf(全的要)
具体用法请 google
public void run() {
for(int pos=0;pos<100;pos++){
jProgressBar1.setValue(pos);
}
}
});
thread.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界面的更改不能在其他线程中进行,不知道是不是这个原因
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界面的更改不能在其他线程中进行,不知道是不是这个原因
这个LookAndFeel还要用一个单独的线程来启动才行
它用线程实现了一些减隐,渐变的特效,也用HighLighter实现了不少效果
但是相对的,Swing本身的对UI进行改变的很多方法都会被Substance的效果所覆盖
HighLighter也完全失效,
也就是说,如果你用了Substance就要完全接受它的一切,除非你能自己修改它的核心代码我以前也试过这个LookAndFeel,
但是我发现它把我很多自己优化界面的东西覆盖掉了,只能放弃
SwingUtilities.invokeLater(new Runnable(){
public void run(){
processBar.setValue(i); }
});
不要把IO相关的操作放到界面更新队列里面去
但swing也可以多线程啊 !!
Swing的多线程和其他服务器程序的多线程还是有些差别的,Swing在考虑多线程的同时还要注意界面变化和更新,这些都是要在EDT线程中去实现的。