单选按钮不会立即改变状态

时间:2014-12-18 21:55:59

标签: java swing actionlistener thread-sleep jradiobutton

在我们的项目中,我的队友注意到单选按钮的异常行为,当内部动作监听器有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);
} 
}

2 个答案:

答案 0 :(得分:4)

看起来您希望避免重复启动长时间运行的后台任务。使用父JRadioButton代替JToggleButton,并在后台任务启动时将其名称和操作设置为取消。诸如SwingWorkerFuture使这很方便。使用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的事件调度线程。