在我们的项目中,我的队友注意到单选按钮的异常行为,当内部动作监听器有SwingUtilites.invokeLater调用时。动作侦听器的结构不允许避免此调用,因为它旨在启动另一个线程,然后切换回AWT线程。
有没有办法解决这个问题?我的意思是改变显示组件的状态。
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);
}
}
答案 0 :(得分:4)
看起来您希望避免重复启动长时间运行的后台任务。使用父JRadioButton
代替JToggleButton
,并在后台任务启动时将其名称和操作设置为取消。诸如SwingWorker
的Future
使这很方便。使用JButton
的相关示例为here。
答案 1 :(得分:2)
使用SwingWorker,试试这段代码:
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在单独的工作线程上执行,该线程由事件调度程序线程通过调用execute方法调用。 SwingUtilities.invokeLater方法只是强制在事件调度线程上异步执行run方法,因此调用其中的Thread.sleep会冻结影响GUI的事件调度线程。