我正在尝试用 java 编写一个简单的代码进行测试,只有一个按钮,当你点击它时它会 hibernate 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);
}
您必须将任何长时间运行的任务(在您的情况下是一个简单的 sleep 调用)移到 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(在本例中为启用/禁用按钮)执行任何操作美国东部时间 - 这就是为什么我在 invokeLater
调用中而不是在单独的线程中调用 setEnabled
的原因。
是的,所有 Swing 组件监听器事件调用从一开始就在 EDT 内执行,因此当您开始在 Action 监听器的 actionPerformed
方法内执行代码时,您已经在 EDT 内 - 这就是为什么如果你在那里调用 sleep,你会阻塞整个 UI。