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