我写了一个窗口,上面有一个按钮,点击按钮后启用另一个线程做别的事情,同时按钮设为不可用,当被启动的线程完成后,再把这个按钮置为可用状态。请问应该怎么做?
谢谢

解决方案 »

  1.   

    我尝试在那个线程结束的时候调用主程序的空间直接改状态,但是报异常了:Invalid thread access还有什么方法能解决吗
      

  2.   

    lcwlyl(网络幽灵)   帮我想想办法,窗口控件好像不是线程安全的,不能跨线程操作
      

  3.   

    谢谢  pdvv(我爱花猫) 但是新开的线程不也是不能改UI的东西吗,同样存在线程安全的问题啊
      

  4.   

    肯定可以,因为我做过。大概:窗口类{
      private Thread  你的线程;  private  void initialize() {
         创建控件
         按钮1
         ……
         启动检测线程();
      }    //单击按钮后启动你的线程
        启动检测线程(){
        class RedrawThread extends Thread{
          public void run(){
             if(别的线程.状态 == null){
               设置“按钮1”状态
             }
             else if(别的线程.状态 == "运行"){
               ……
             }
        }
        RedrawThread redraw = new RedrawThread();
        redraw.start();
      }
    }你自己写的那个线程必须定义几种状态。
      

  5.   

    不行,我试了,对了,我用的是SWT控件,可能跟这个有关。pdvv(我爱花猫),你是用的swing吗
      

  6.   

    我用的是swing,不过跟这个没有关系。你自己的线程需要这样:
    public class ThreadTimer extends Thread {
        public final int STATE_STOPPED  = 0;
        public final int STATE_RUNNING  = 1;
        public final int STATE_WAITTING = 2;
        private int timerState = STATE_STOPPED;     private boolean bRunning = false;
      
        public void run(){
            bRunning = true;
            while(bRunning){
                
                setTimerState(STATE_RUNNING);
                yield();
                
                doSomething();
               
                setTimerState(STATE_WAITTING);
                try{
                    sleep(N * 1000);
                }
                catch(Exception e){
                    e.printStackTrace();            
                }
            }
        }     /**
         * @param timerState 要设置的 timerState。
         */
        public void setTimerState(int timerState) {
            this.timerState = timerState;
        }    //查询当前运行状态
        public int getTimerState(){
            return this.timerState;
        }    public void doSomething(){}
    }
      

  7.   

    SWING里面有个ACTION的嘛,可以实现你说的
      

  8.   

    写了个简单的例子,用的AWT,你要的应该是这样吧。
    import java.awt.*;
    import java.awt.event.*;
    class Run extends Thread
    {
    Button button;
    public Run(Button button)
    {
    this.button = button;
    }
    public void run()
    {
    button.setName("running...");
    boolean flag = true;
    while(flag)
    {        //做其它事情;
    try
    {Thread.sleep(5000);}
    catch(Exception e) {}
    flag = false;
    }
    button.setName("run over.");
    button.setEnabled(true);
    }
    }
    class test3 extends Frame
    {
    Button button = new Button("click");
    public test3()
    {
    button.setBounds(150,100,100,30);
    button.addActionListener(
    new ActionListener()
    {
    public void actionPerformed(ActionEvent e)
    {
    button.setEnabled(false);
    new Run(button).start();
    }
    });
    this.setLayout(null);
    this.add(button);
    }
    public static void main(String [] args)
    {
    test3 frame = new test3();
    frame.addWindowListener(
    new WindowAdapter()
    {
    public void windowClosing(WindowEvent e)
    {
    System.exit(0);
    }
    });
    frame.setSize(400,300);
    frame.setVisible(true);
    }
    }
      

  9.   

    谢谢楼上的几位
    pdvv(我爱花猫)和lh8748(LH)的方法我都试过了,swing和awt都是没问题的,但是swt在另一个线程里操作控件的时候会抛异常:
    org.eclipse.swt.SWTException: Invalid thread access
    at org.eclipse.swt.SWT.error(SWT.java:2691)
    at org.eclipse.swt.SWT.error(SWT.java:2616)
    at org.eclipse.swt.SWT.error(SWT.java:2587)
    at org.eclipse.swt.widgets.Widget.error(Widget.java:381)
    at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:284)
    at org.eclipse.swt.widgets.Button.setText(Button.java:602)
    at test.Run.run(Run.java:16)我把lh8748(LH)的代码改成SWT的运行就是上面的结果,当然,原本awt的环境是没问题的
    修改后的代码如下:
    import org.eclipse.swt.events.SelectionEvent;
    import org.eclipse.swt.events.SelectionListener;
    import org.eclipse.swt.widgets.Button;
    import org.eclipse.swt.widgets.Display;
    import org.eclipse.swt.widgets.Shell;class test3
    {    public test3()
        {        Display display = new Display();
            Shell shell = new Shell(display);
            shell.setLocation(250, 100);        final Button button = new Button(shell, 0);
            button.setBounds(150, 100, 100, 30);
            button.addSelectionListener(new SelectionListener() {            public void widgetSelected(SelectionEvent e)
                {
                    new Run(button).start();
                    button.setEnabled(false);
                }            public void widgetDefaultSelected(SelectionEvent e)
                {
                    // TODO Auto-generated method stub            }        });        shell.pack();
            shell.open();        while (!shell.isDisposed())
            {
                if (!display.readAndDispatch())
                    display.sleep();
            }
            display.dispose();
            System.exit(0);
        }    public static void main(String[] args)
        {        test3 frame = new test3();    }
    }import org.eclipse.swt.widgets.Button;class Run extends Thread
    {
        Button button;    public Run(Button button)
        {
            this.button = button;
        }    public void run()
        {
            button.setText("running...");
            boolean flag = true;
            while (flag)
            { //做其它事情;
                try
                {
                    Thread.sleep(5000);
                }
                catch (Exception e)
                {
                }
                flag = false;
            }
            button.setText("run over.");
            button.setEnabled(true);
        }
    }
      

  10.   

    楼主,俺又转回来了,我今天刚开始学习使用SWT(不好意思),有点感觉,联想到你的问题,可能对你有帮助。java语言本身支持多线程,虽然很好但是不利于GUI编程,因为它不能保证图形控件操作的同步。但是在SWT中,采用的是一种简化,通常只允许唯一一个“用户线程”对图形控件进行操作。其他线程中如果调用,就会抛出org.eclipse.swt.SWTException。如果非要这么作,在包org.eclipse.swt.widget.Display中提供方法syncExec(Runnable)、asyncExec(Runnable)方法。所以,你的程序稍作修改就可以了:            public void widgetSelected(SelectionEvent e)
                {
                    Display.getCurrent().syncExec(new Run(button));
                    
                   //button.setEnabled(false);我把这句放到了Run.run()中了,为了和button.setEnabled(true);对应
    新学SWT,有不懂之处请多指教。
                    
                }
      

  11.   

    用Swing工具:SwingUtilities.invokeLater();
      

  12.   

    看 java thread programming
      

  13.   

    invokeLater是用在线程中对UI的更新。问楼主:当被启动的线程完成后,再把这个按钮置为可用状态,没看出这有什么线程不安全。你所理解的线程不安全是什么意思?
      

  14.   

    sorry,各位,好久没来了,问题已经解决了 :) gemouzhi(gemouzhi),我碰到了异常是:
    org.eclipse.swt.SWTException: Invalid thread access
    at org.eclipse.swt.SWT.error(SWT.java:2691)
    at org.eclipse.swt.SWT.error(SWT.java:2616)
    at org.eclipse.swt.SWT.error(SWT.java:2587)
    at org.eclipse.swt.widgets.Widget.error(Widget.java:381)
    at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:284)
    at org.eclipse.swt.widgets.Button.setText(Button.java:602)
    at test.Run.run(Run.java:16)
    我觉得这个应该是线程异常,现在问题解决了,理解不太深,好像是这样的:SWT里对控件的管理只能由一个主线程来完成,任何其他线程试图修改控件都会抛出上面这个异常。解决方法就是让其他线程完成工作是,给主线程发一个消息,还是由主线程来完成控件的修改工作。//主线程
    public class MainWindow {    public Outputer out = null;
        Object o = new Object();
        ....
        ....
        ....
        Button bRun = new Button(shell,SWT.NONE);
        registerCallback(bRun, SWT.Selection, this, "doRun");
        ....
        ....
        ....
        public void doRun(Event event) { bRun.setEnabled(false);
    // start a new thread to wait
    new Thread(new Runnable() {
    public void run() {
    try {
    synchronized (o) {
    o.wait();
    }
    } catch (InterruptedException ex) {
    ex.printStackTrace();
    }
    display.asyncExec(new Runnable() {
    public void run() {
    bRun.setEnabled(true);
    }
    });
    }
    }).start(); // start outputer processor
    new Outputer(o);
    }
    }
    public class Outputer extends Thread
    {
        String COMMAND = null;
        String line;
        Process p = null;
        Object o = null;    public Outputer(Object o)
        {
            this.o = o;
            start();
        }    public void run()
        {
            //你要作的事情
            SomethingYouWantToDo();        synchronized (o)
            {
                o.notify();
            }
        }
    }不知道说清楚没有,反正运行结果是满足我的需求的。