简体   繁体   English

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

[英]Radio button doesn't change the state immediately

In our project my teammate notice unusual behavior for radio button, when inside action listener there is SwingUtilites.invokeLater call. 在我们的项目中,我的队友注意到单选按钮的异常行为,在动作侦听器内部时,有SwingUtilites.invokeLater调用。 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. 动作侦听器的体系结构不允许避免此调用,因为它旨在启动另一个线程,然后切换回AWT线程。

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);
} 
}

It looks like you want to avoid repeatedly initiating a long running background task. 您似乎要避免重复启动长时间运行的后台任务。 Instead of a JRadioButton , use the parent JToggleButton , and set it's name and action to Cancel when the background task is started. 代替JRadioButton ,使用父级JToggleButton ,并在启动后台任务时将其名称和操作设置为Cancel A Future such as SwingWorker makes this convenient. 诸如SwingWorker Future类的Future使得此操作很方便。 A related example using JButton is seen here . 在这里看到一个使用JButton的相关示例。

Use SwingWorker, try this code: 使用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 is executed on separate worker thread which is invoked by event dispatcher thread by calling execute method. SwingWorker在单独的工作线程上执行,事件调度程序线程通过调用execute方法调用该工作线程。 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. SwingUtilities.invokeLater方法只是将run方法强加为在事件分配线程上异步执行,因此在其内部调用Thread.sleep将冻结影响GUI的事件分配线程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM