问题描述
在我们的项目中,我的队友注意到单选按钮的异常行为,当在动作监听器中进行SwingUtilites.invokeLater调用时。动作侦听器的体系结构不允许避免此调用,因为它旨在启动另一个线程,然后切换回AWT线程。
In our project my teammate notice unusual behavior for radio button, when inside action listener there is SwingUtilites.invokeLater call. Archetecture of the action listener doesn't allow to avoid this call because is designed to start another thread, and then there is a switch back to AWT thread.
解决这个问题的方法?我的意思是更改显示组件的状态。
Is there a way to fix this? I mean change the state of displayed component.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.WindowConstants;
public class RadioButtonTest {
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
| UnsupportedLookAndFeelException e1) {
e1.printStackTrace();
}
JFrame frame = new JFrame();
JPanel panel = new JPanel();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.add(panel);
ButtonGroup group = new ButtonGroup();
JRadioButton b1 = new JRadioButton("Button 1");
final JRadioButton b2 = new JRadioButton("Button 2");
b2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
Runnable action = new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2500);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
}
};
SwingUtilities.invokeLater(action);
}
});
group.add(b1);
group.add(b2);
panel.add(b1);
panel.add(b2);
frame.setVisible(true);
}
}
推荐答案
使用SwingWorker,请尝试以下代码:
Use SwingWorker, try this code:
public void actionPerformed(ActionEvent arg0) {
SwingWorker<Object,Object> sw = new SwingWorker<Object,Object>()
{
@Override
protected Object doInBackground() throws Exception
{
try {
Thread.sleep(2500);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
return null;
}
};
sw.execute();
}
SwingWorker在单独的工作线程上执行,该事件由事件调度程序线程通过调用来调用执行方法。 SwingUtilities.invokeLater方法只是将run方法强加在事件分配线程上异步执行,因此在其内部调用Thread.sleep将冻结影响GUI的事件分配线程。
SwingWorker is executed on separate worker thread which is invoked by event dispatcher thread by calling execute method. SwingUtilities.invokeLater method just imposes run method to be executed asynchronously on the event dispatching thread, so calling Thread.sleep inside it will freezes the event dispatch thread which affects the GUI.
这篇关于单选按钮不会立即更改状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!