(转载1)
楼主bluepb(流星) 2005-06-04 20:28:17 在 Java / GUI 设计 提问
我现在在用jAVA做图形化设计,想问个多线程的问题。
比如在一个窗口上点个按钮执行一个操作,这个操作至少要花10秒钟,如何不让这个窗口在执行中没相应,比如下面一个文本框,随时在显示着执行的时间。
不要跟我说不用多线程就可以实现,因为我认为是不可能的。
哪位高手能否给个GUI中这样的一个例子。谢谢!
---------------------------------------------------------------------------------------
1 楼yxxcrtd(Report中) 回复于 2005-06-05 11:34:52 得分 0
Uping.....
---------------------------------------------------------------------------------------
2 楼chenweionline(键盘上的舞者) 回复于 2005-06-05 11:54:01 得分 0
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class ThreadTest extends JFrame{
JTextField txt = new JTextField();
JButton btn = new JButton("start");
ThreadTest(){
btn.addActionListener(new AbstractAction(){
public void actionPerformed(ActionEvent event){
// 耗时操作线程
new Thread(){
public void run(){
for(int i=0;i<10;i++){
txt.setText(i+" seconds");
try{
sleep(1000);
}
catch(Exception ex){
ex.printStackTrace();
}
}
txt.setText("finished");
}
}.start();
}
});
this.getContentPane().add(btn,BorderLayout.NORTH);
this.getContentPane().add(txt,BorderLayout.CENTER);
}
public static void main(String[] args){
JFrame frame = new ThreadTest();
frame.pack();
frame.setVisible(true);
}
}
---------------------------------------------------------------------------------------
3 楼chenweionline(键盘上的舞者) 回复于 2005-06-05 11:55:38 得分 0
这只是一个演示例子,最好不要在事件派发线程以外的线程里更新组件。
---------------------------------------------------------------------------------------
4 楼SaKura2003(小飞仔) 回复于 2005-06-05 15:22:51 得分 0
不要跟我说不用多线程就可以实现,因为我认为是不可能的。
只有想不到,没有做不到的。
---------------------------------------------------------------------------------------
5 楼wuyafeixue(蓝色天空) 回复于 2005-06-05 20:09:40 得分 0
这是我写的读一个文件的线程,当点击open按钮时,执行下面的线程
private ActionListener open=new ActionListener(){
public void actionPerformed(ActionEvent e){
try{
new threadOpen().start();
}catch(Exception f){
System.err.println("error");
}
}
};
private class threadOpen extends Thread{
private BufferedReader in;
threadOpen(){
}
public void run(){
JFileChooser c=new JFileChooser();
JFrame frame = getFrame();
c.showOpenDialog(frame);
try{
String name=c.getSelectedFile().getName();
String dir=c.getCurrentDirectory().toString();
dir=dir.replaceAll("\\\\","\\\\\\\\");
String openName=dir+"\\"+name;
in=new BufferedReader(new FileReader(openName));
txt.setText("");
String s = null;
String s2=new String();
int size=0,counter=0;
while((s = in.readLine())!= null){
s=s+"\n";
if(++counter%100==0)
sleep(10);
txt.getDocument().insertString(size,s,null);
size+=s.length();
}
in.close();
jmi61.setEnabled(false);
jmi62.setEnabled(false);
}catch(Exception e){
System.err.println("error");
}
}
}
(转载2)
楼主PHMan() 2003-12-24 13:05:06 在 Java / J2SE / 基础类 提问当我触发一个BUTTON事件后,程序将执行一段耗时的操作(大约30分钟),这时SWING界面将”死”掉了,在耗时操作完成之前,将不会有任何反映。我想把这个耗时操作用invokeLater() 去执行,但是在这个操作完成之前,SWING界面还是没反映。大家是否有经验解决过这种问题?谢谢。
----------------------------------------------------------------------------------------
1 楼ManFirst(春梦空陶醉,醒来梦已碎.) 回复于 2003-12-24 13:11:11 得分 0
多线程可解决。
就是隔多少秒,执行一下。
----------------------------------------------------------------------------------------
2 楼ManFirst(春梦空陶醉,醒来梦已碎.) 回复于 2003-12-24 13:15:55 得分 0
timer = new javax.swing.Timer(8, createTextLoadAction());
timer.start();
public Action createTextLoadAction() {
return new AbstractAction("text load action") {
public void actionPerformed (ActionEvent e) {
if(jProgressBar1.getValue() < jProgressBar1.getMaximum()) {
jProgressBar1.setValue(jProgressBar1.getValue() +1);
tmp_CheckDb.getResultCheck(jProgressBar1.getValue());//你的程序
jLabel2.setText("目前已经检查:"+jProgressBar1.getValue()+"/"+jProgressBar1.getMaximum());
} else {
if(timer != null) {
timer.stop();
timer = null;
}
}
}
};
}
----------------------------------------------------------------------------------------
3 楼PHMan() 回复于 2003-12-24 14:26:52 得分 0
谢谢。从你的代码中,我怎么确定jProgressBar1.getMaximum()的值。因为我要执行一段耗时操作。但我没法确定要多少时间(30分钟只是一个例子)。所以我觉得没法确定getMaximum()的值。另外一点就是如果任务不能很快的完成,也许应该用SwingWorker 而不是Timer.
----------------------------------------------------------------------------------------
4 楼xxisxx(xx) 回复于 2003-12-24 16:14:56 得分 0
关注!
我也再做这方面的调查,大家共同探讨
UP
-----------------------------------------------------------------------------------------
5 楼ManFirst(春梦空陶醉,醒来梦已碎.) 回复于 2003-12-24 16:36:12 得分 5
timer = new javax.swing.Timer(8, createTextLoadAction());//关键是这句了。
timer.start();
------------------------------------------------------------------------------------------
6 楼xxisxx(xx) 回复于 2003-12-24 17:03:01 得分 5
我从别处找来了这样一个例子,不知道对你又无帮助
package cosmos.alm;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/** * 事件处理过程中UI的刷新 * @author Bruce * @version 1.0 */
public class TestUIUpdate2 {
public TestUIUpdate2() {
TestUIUpdate2Frame frame = new TestUIUpdate2Frame();
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
new TestUIUpdate2();
}
}
class TestUIUpdate2Frame
extends JFrame {
JTextPane pane = new JTextPane();
JButton button = new JButton("action...");
TestUIUpdate2Frame() {
init();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
new Thread() {
public void run() {
try {
showMessage("step one...");
Thread.sleep(3000);
showMessage("\nstep two...");
Thread.sleep(3000);
showMessage("\nfinished.");
Thread.sleep(3000);
}
catch (InterruptedException ie) {
//ignored
}
}
}.start();
}
});
}
private void showMessage (final String msg) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
pane.setText(pane.getText() + msg);
}
});
}
private void init() {
pane.setPreferredSize(new Dimension(300, 200));
Container content = getContentPane();
content.setLayout(new BorderLayout());
content.add(pane, BorderLayout.CENTER);
content.add(button, BorderLayout.SOUTH);
}
}
它把按钮的action事件坐到一个线程里,然后用SwingUtilities.invokeLater调用
-----------------------------------------------------------------------------------------------
7 楼sallina(我想骂人!!) 回复于 2003-12-24 17:14:01 得分 0
楼上正解!
-----------------------------------------------------------------------------------------------
8 楼binny(骑个破车看夕阳) 回复于 2003-12-24 17:41:17 得分 10
http://www.javaresearch.org/article/showarticle.jsp?column=287&thread=4429
-----------------------------------------------------------------------------------------------
9 楼PHMan() 回复于 2003-12-25 01:22:36 得分 0
谢谢大家的帮助,我已经解决了这个问题。事实上只要把耗时操作放到一个新线程里去就够了。然后在事件中运行这个线程。
Thread t = new Thread(){
public void run(){
//我的耗时操作
}
};
t.start() ;
很感谢ManFirst 和xxisxx, 但我觉得binny给我的链接很好,所以我把分说给他。祝大家圣诞快乐。
------------------------------------------------------------------------------------------------------------
(注:该方案可行!更多内容可以浏览我的其他文章,有详细测试!!!)