3

我在java中尝试了一个简单的代码进行测试,当你点击它时只是一个按钮,它会休眠5秒,这是处理程序

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt)    {                                               
    try {
        System.out.println ("hiiii");
        Thread.sleep (5000);
        System.out.println ("bye");        
    } catch (InterruptedException ex) {
        Logger.getLogger(NewJFrame.class.getName()).log(Level.SEVERE, null, ex);
    }
} 

我希望此按钮在完成工作(5 秒)之前不会收到任何事件,我尝试在处理程序中禁用和启用它但徒劳无功

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         

    jButton1.setEnabled(false);

    try {
        System.out.println ("hiiii");
        Thread.sleep (5000);
        System.out.println ("bye");        
    } catch (InterruptedException ex) {
        Logger.getLogger(NewJFrame.class.getName()).log(Level.SEVERE, null, ex);
    }

    jButton1.setEnabled(true);
} 
4

1 回答 1

2

您必须将任何长时间运行的任务(在您的情况下是一个简单的睡眠调用)移到 EDT(事件调度线程)之外 - 该线程用于呈现 UI,如果您通过某些操作阻止它 - 您会阻止所有 UI立刻。

这是一个如何禁用/启用按钮的正确示例:

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * @author Mikle Garin
 * @see http://stackoverflow.com/a/18590057/909085
 */

public class ButtonSleep
{
    public static void main ( String[] args )
    {
        JFrame frame = new JFrame ( "Custom list renderer" );

        final JButton button = new JButton ( "Make me sleep 5 seconds" );
        button.addActionListener ( new ActionListener ()
        {
            @Override
            public void actionPerformed ( ActionEvent e )
            {
                button.setEnabled ( false );
                new Thread ( new Runnable ()
                {
                    @Override
                    public void run ()
                    {
                        try
                        {
                            Thread.sleep ( 5000 );
                        }
                        catch ( InterruptedException e1 )
                        {
                            //
                        }
                        SwingUtilities.invokeLater ( new Runnable ()
                        {
                            @Override
                            public void run ()
                            {
                                button.setEnabled ( true );
                            }
                        } );
                    }
                } ).start ();
            }
        } );
        frame.add ( button );

        frame.pack ();
        frame.setLocationRelativeTo ( null );
        frame.setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );
        frame.setVisible ( true );
    }
}

是的,这看起来很奇怪,但是您必须将操作移至单独的线程(哪个线程并不重要),并且您必须使用 EDT 内的 UI(在本例中 - 启用/禁用按钮)执行任何操作 - 那这就是为什么我打电话而不是setEnabledinvokeLater单独的线程内打电话的原因。

是的,所有 Swing 组件侦听器事件调用从一开始就在 EDT 内执行,因此当您开始在actionPerformed动作侦听器的方法内执行代码时,您已经在 EDT 内 - 这就是如果您在那里调用 sleep 会阻塞整个 UI 的原因。

于 2013-09-03T10:35:02.337 回答