问题描述
最近在做一个C/S的通行软件,其中涉及到文件传输的功能,希望能够显示文件的上传进度,但是遇到一些问题无法解决:当传输文件时,进度条必须不断更新,但是Swing好像是单线程的,而且对Swing界面的更改不能在其他线程中进行(如果有错请指教),结果我现在的问题就是文件传输的过程中进度条不能更新,而且整个界面被阻塞,导致对界面无法进行其他操作,只有文件传输完成后才突然显示100%,下面贴出部分代码:包含进度条的类:publicclassTransmitBarextendsJPanel{privateFilefile;privateJProgressBarprogressBar;publicTransmitBar(Filefile){this.file=file;progressBar=newJProgressBar(0,(int)file.length());progressBar.setStringPainted(true);progressBar.setValue(0);progressBar.setPreferredSize(newDimension(215,20));this.setLayout(null);progressBar.setBounds(0,0,215,15);this.add(progressBar);this.setPreferredSize(newDimension(215,15));}publicTransmitBargetObj(){returnthis;}publicvoidstart(){SwingUtilities.invokeLater(newRunnable(){publicvoidrun(){try{FileInputStreamfis=newFileInputStream(file);FileOutputStreamfos=newFileOutputStream("D:\"+file.getName());intdata;inti=0;while((data=fis.read())!=-1){fos.write(data);i++;progressBar.setValue(i);//getObj().repaint();//getObj().updateUI();}//Thread.interrupted();}catch(Exceptione){}}});}}主窗体中通过按钮激发文件选择,将选择的文件传入上面类的构造方法中,然后调用类的start()方法,现在文件可以传输,但是进度条无法更新:
解决方案
解决方案二:
使用SwingWorker。具体用法请google
解决方案三:
我一直这么用。Threadthread=newThread(newRunnable(){publicvoidrun(){for(intpos=0;pos<100;pos++){jProgressBar1.setValue(pos);}}});thread.start();
解决方案四:
还是不行,我把start()方法改成如下:publicvoidstart(){Threadthread=newThread(newRunnable(){publicvoidrun(){try{FileInputStreamfis=newFileInputStream(file);FileOutputStreamfos=newFileOutputStream("D:\"+file.getName());intdata;inti=0;while((data=fis.read())!=-1){fos.write(data);i++;progressBar.setValue(i);getObj().repaint();getObj().updateUI();}}catch(Exceptione){}}});thread.start();}结构出现异常(我使用了Substance来美化界面):org.jvnet.substance.api.UiThreadingViolationException:ComponentstatechangemustbedoneonEventDispatchThreadatorg.jvnet.substance.utils.SubstanceCoreUtilities.testComponentStateChangeThreadingViolation(SubstanceCoreUtilities.java:2386)atorg.jvnet.substance.SubstanceProgressBarUI$1.stateChanged(SubstanceProgressBarUI.java:156)atjavax.swing.DefaultBoundedRangeModel.fireStateChanged(UnknownSource)atjavax.swing.DefaultBoundedRangeModel.setRangeProperties(UnknownSource)atjavax.swing.DefaultBoundedRangeModel.setValue(UnknownSource)atjavax.swing.JProgressBar.setValue(UnknownSource)atclient.ui.file.TransmitBar$1.run(TransmitBar.java:85)atjava.lang.Thread.run(UnknownSource)错误就是progressBar.setValue(i);这一句,在网上看到这样一句话:Swing界面的更改不能在其他线程中进行,不知道是不是这个原因
解决方案五:
还是不行,我把start()方法改成如下:publicvoidstart(){Threadthread=newThread(newRunnable(){publicvoidrun(){try{FileInputStreamfis=newFileInputStream(file);FileOutputStreamfos=newFileOutputStream("D:\"+file.getName());intdata;inti=0;while((data=fis.read())!=-1){fos.write(data);i++;progressBar.setValue(i);getObj().repaint();getObj().updateUI();}}catch(Exceptione){}}});thread.start();}结构出现异常(我使用了Substance来美化界面):org.jvnet.substance.api.UiThreadingViolationException:ComponentstatechangemustbedoneonEventDispatchThreadatorg.jvnet.substance.utils.SubstanceCoreUtilities.testComponentStateChangeThreadingViolation(SubstanceCoreUtilities.java:2386)atorg.jvnet.substance.SubstanceProgressBarUI$1.stateChanged(SubstanceProgressBarUI.java:156)atjavax.swing.DefaultBoundedRangeModel.fireStateChanged(UnknownSource)atjavax.swing.DefaultBoundedRangeModel.setRangeProperties(UnknownSource)atjavax.swing.DefaultBoundedRangeModel.setValue(UnknownSource)atjavax.swing.JProgressBar.setValue(UnknownSource)atclient.ui.file.TransmitBar$1.run(TransmitBar.java:85)atjava.lang.Thread.run(UnknownSource)错误就是progressBar.setValue(i);这一句,在网上看到这样一句话:Swing界面的更改不能在其他线程中进行,不知道是不是这个原因
解决方案六:
哟,这个还真不知道了。帮你UP
解决方案七:
原来还用了substance啊,这个真的不好说了这个LookAndFeel还要用一个单独的线程来启动才行它用线程实现了一些减隐,渐变的特效,也用HighLighter实现了不少效果但是相对的,Swing本身的对UI进行改变的很多方法都会被Substance的效果所覆盖HighLighter也完全失效,也就是说,如果你用了Substance就要完全接受它的一切,除非你能自己修改它的核心代码我以前也试过这个LookAndFeel,但是我发现它把我很多自己优化界面的东西覆盖掉了,只能放弃
解决方案八:
解决方案九:
新手想看看
解决方案十:
还是用swingworker比较好,很不错
解决方案十一:
你把更新界面的代码放在SwingUtilities.invokeLater(newRunnable(){publicvoidrun(){processBar.setValue(i);}});不要把IO相关的操作放到界面更新队列里面去
解决方案十二:
引用7楼huntor的回复:
14.32.14.SwingWorkerandProgressBar
顶这个。将上传的逻辑处理放在doInBackground方法中,在publish方法中可以更新你的JProgressBar组件,详见API中的SwingWoker说明。
解决方案十三:
帮定,祝你好运
解决方案十四:
除了SwingWorker,其他Thread实现都是不安全的
解决方案十五:
本人新手学习学习!
解决方案:
这个可以算的。。。。但swing也可以多线程啊!!
解决方案:
引用15楼asliuyajun的回复:
这个可以算的。。。。但swing也可以多线程啊!!
Swing的多线程和其他服务器程序的多线程还是有些差别的,Swing在考虑多线程的同时还要注意界面变化和更新,这些都是要在EDT线程中去实现的。