Swing调用EANDWAIT

Swing调用EANDWAIT,swing,events,user-interface,Swing,Events,User Interface,我正在学习Swing并创建了一个示例GUI。我正试图以准确的顺序实现以下目标 用户在某些文本字段中输入文本 用户单击“启动”按钮 将禁用“启动”按钮。 后台线程生成并处理文本字段中的文本 背景线结束 再次启用“启动”按钮。 我试图使用invokeandwait,如下所示,但我得到“无法从事件调度程序线程调用invokeandwait”。我的主要方法在同一个.class文件中,我不太确定“事件调度程序线程”到底是什么。对于这样的事情,最好的方法是什么?我是否需要在我的工作线程中设置某种警报以路由回

我正在学习Swing并创建了一个示例GUI。我正试图以准确的顺序实现以下目标

  • 用户在某些文本字段中输入文本
  • 用户单击“启动”按钮
  • 将禁用“启动”按钮。
  • 后台线程生成并处理文本字段中的文本
  • 背景线结束
  • 再次启用“启动”按钮。
  • 我试图使用invokeandwait,如下所示,但我得到“无法从事件调度程序线程调用invokeandwait”。我的主要方法在同一个.class文件中,我不太确定“事件调度程序线程”到底是什么。对于这样的事情,最好的方法是什么?我是否需要在我的工作线程中设置某种警报以路由回“事件调度程序线程”

    启动按钮代码

    private void launchButtonActionPerformed(java.awt.event.ActionEvent evt) {                                             
    
            launchButton.setEnabled(false);
    
            try {
                java.awt.EventQueue.invokeAndWait(new MyTestThread());
            } catch (Exception e) {
            }
    
            launchButton.setEnabled(true);    
    
        }   
    
    工作线程

    public class MyTestThread extends Thread {
    
        private int i = 0;
    
        public void run() {
    
            while (i < 5) {
    
                try {
                    System.out.println(i++);
                    sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    
        }
    
    }
    
    public class WorkerThread extends SwingWorker<Integer[], Void> {
    
        @Override
        public Integer[] doInBackground() {
    
            System.out.println("Doing in background");
    
            for (int i = 0; i < 5; i++) {
                try {
                    Thread.sleep(1000);
                    System.out.println("Doing in background" + i);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    
            return null;
        }
    
        @Override
        public void done() {
            System.out.println("Swingworker is Done");
        }
    }
    
    事件分派线程(EDT)是唯一允许访问Swing类和(几乎所有)方法的线程。GUI的所有初始化和事件都由EDT执行。要在EDT中执行某些操作,必须使用
    SwingUtilities.invokeLater
    invokeAndWait
    (这相当于
    EventQueue.invokexx
    )。这就是为什么所有Swing程序都以
    SwingUtilities.invokeLater()开头的主要原因:在EDT中执行GUI初始化

    当EDT繁忙时,UI冻结,这就是为什么后台线程很有用。当您需要独立于UI进行大量工作(计算、I/O、传输等)时,您必须使用“工作线程”

    有关Swing中线程的更多信息,请参见本教程:

    现在,您试图完成的是正确的,但您使用的工具却不是

    您需要知道两件事:如何处理事件(如按钮按下)和如何创建后台线程

    有关第一个示例,请参见本教程:

    您只需将
    ActionListener
    添加到按钮,每当按钮抛出事件时,将在EDT中执行侦听器的
    actionPerformed
    方法

    最简单的例子:

    JButton button = new JButton("Test button");
    button.addActionListener(new ActionListener()
    {
        public void actionPerformed(ActionEvent event)
        {
            System.out.println("The button was pressed.");
        }
    }
    
    event
    变量包含有用的信息,例如event.getSource()返回抛出事件的对象,在本例中为按钮

    现在,当按下按钮时,您要做的是创建一个工作线程。工作线程是使用SwingWorker类创建的,正如您在并发教程中看到的那样。在那里,您可以定义将在后台线程中执行的一段代码(在
    doInBackground()
    方法中)和将在后台工作完成后在EDT中执行的一段代码(在
    done()
    方法中)

    所以你想做这样的事情:

    private static  JButton _button;
    
    //...
    _button = new JButton("Test button");
    
    _button.addActionListener(new ActionListener()
    {
        public void actionPerformed(ActionEvent event)
        {
            System.out.println("The button was pressed.");
            _button.setEnabled(false);
            SwingWorker worker = new SwingWorker()
            {
                @Override
                protected Object doInBackground() throws Exception
                {
                    //do something useful in the background thread
                    return null;
                }
    
                @Override
                protected void done()
                {
                    _button.setEnabled(true);
                }
            }
            worker.execute();
        }
    }
    

    关于这件事有很多信息。阅读这些类的Java参考资料,阅读官方教程并在SO中搜索。关于SwingWorkers的另一个很好的教程是:

    不要阻止EDT(事件调度线程)-发生这种情况时,GUI将“冻结”。不要调用
    Thread.sleep(n)
    为长时间运行的任务实现
    SwingWorker
    。有关更多详细信息,请参阅。感谢您的详细回复!很抱歉我迟了回复,自从我上一次发帖后,有一些事情发生了。。。解决方案已附加到我原来的帖子中
    private static  JButton _button;
    
    //...
    _button = new JButton("Test button");
    
    _button.addActionListener(new ActionListener()
    {
        public void actionPerformed(ActionEvent event)
        {
            System.out.println("The button was pressed.");
            _button.setEnabled(false);
            SwingWorker worker = new SwingWorker()
            {
                @Override
                protected Object doInBackground() throws Exception
                {
                    //do something useful in the background thread
                    return null;
                }
    
                @Override
                protected void done()
                {
                    _button.setEnabled(true);
                }
            }
            worker.execute();
        }
    }