使按钮无响应一段时间java

时间:2013-09-03 09:54:02

标签: java swing

我在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);
} 

1 个答案:

答案 0 :(得分:2)

你必须在EDT(事件调度线程)之外移动任何长时间运行的任务(在你的情况下它是一个简单的睡眠调用) - 该线程用于呈现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 );
    }
}

是的,这看起来很奇怪,但你必须将你的操作移到一个单独的线程(并不重要的是哪个线程),你必须用UI执行任何操作(在这种情况下 - 启用/禁用按钮) EDT - 这就是为什么我在setEnabled调用中调用invokeLater而不是在单独的线程内。

是的,所有Swing组件侦听器事件调用都是从头开始在EDT中执行的,所以当你开始在动作监听器的actionPerformed方法中执行代码时,你已经在EDT中 - 这就是为什么你阻止如果你在那里打电话给整个UI。