Выбор JRadioButton не отображается в графическом интерфейсе, пока не отображается в Windows L&F

В настоящее время я работаю над проектом, который требует изменения состояния JRadioButton при обновлении просматриваемой записи.

У нас было несколько клиентов, которые жаловались нам на то, что при изменении записи, если JRadioButton находится за пределами экрана, она не будет обновляться, пока не появится экран. Такое поведение, по-видимому, является результатом использования Windows Look & Feel, так как оно не происходит, когда оно не установлено.

Пример кода ниже демонстрирует это. По умолчанию выбранным JRadioButton является "Cat", поэтому, выбрав "Dog" JButton и затем изменив вкладку на "Question", вы увидите, что происходит переход JRadioButton.

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

/**
 * Example of JRadioButton not updating until it's parent panel becomes visible.
 */
public class RadioButtonExample extends JPanel implements ActionListener {

    public static final String CAT  = "Cat";
    public static final String DOG  = "Dog";

    private final JRadioButton radCat;
    private final JRadioButton radDog;
    private final ButtonGroup grpAnimal;

    public RadioButtonExample() {
        super(new BorderLayout());

        JLabel lblQuestion = new JLabel("Are you a cat or dog person?");

        radCat = new JRadioButton(CAT);
        radCat.setActionCommand(CAT);
        radCat.setSelected(true);

        radDog = new JRadioButton(DOG);
        radDog.setActionCommand(DOG);

        grpAnimal = new ButtonGroup();
        grpAnimal.add(radCat);
        grpAnimal.add(radDog);

        JPanel pnlQuestion = new JPanel(new GridLayout(0, 1));
        pnlQuestion.add(lblQuestion);
        pnlQuestion.add(radCat);
        pnlQuestion.add(radDog);

        JButton btnSetCat = new JButton(CAT);
        btnSetCat.setActionCommand(CAT);
        btnSetCat.addActionListener(this);

        JButton btnSetDog = new JButton(DOG);
        btnSetDog.setActionCommand(DOG);
        btnSetDog.addActionListener(this);

        JPanel pnlButtons = new JPanel(new GridLayout(0, 1));
        pnlButtons.add(new JLabel("Update your choice of animal"));
        pnlButtons.add(btnSetCat);
        pnlButtons.add(btnSetDog);

        JTabbedPane tabPane = new JTabbedPane();
        tabPane.addTab("Buttons", pnlButtons);
        tabPane.addTab("Question", pnlQuestion);

        add(tabPane, BorderLayout.LINE_START);
        setBorder(BorderFactory.createEmptyBorder(20,20,20,20));
    }

    public void actionPerformed(ActionEvent evt) {
        SwingUtilities.invokeLater(new Runnable(){
            public void run() {
                grpAnimal.clearSelection();
                if (CAT.equals(evt.getActionCommand())) {
                    grpAnimal.setSelected(radCat.getModel(), true);
                }
                else if (DOG.equals(evt.getActionCommand())) {
                    grpAnimal.setSelected(radDog.getModel(), true);
                }
            }
        });

    }

    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private static void createAndShowGUI() {
        //Create and set up the window.
        JFrame frame = new JFrame("RadioButtonExample");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Create and set up the content pane.
        JComponent newContentPane = new RadioButtonExample();
        newContentPane.setOpaque(true);
        frame.setContentPane(newContentPane);

        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        // Comment out the line below to run using standard L&F
        setLookAndFeel();

        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }

    private static void setLookAndFeel() {
        try {
            // Set Windows L&F
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
        } 
        catch (Exception e) {
           // handle exception
        }
    }
}

Есть ли способ предотвратить такое поведение или даже ускорить его, чтобы сделать его менее заметным для наших пользователей?

1 ответ

Решение

Вы можете отключить анимацию, указав swing.disablevistaanimation Системное свойство Java:

java -Dswing.disablevistaanimation="true" your-cool-application.jar

в com.sun.java.swing.plaf.windows.AnimationController класс, есть VISTA_ANIMATION_DISABLED поле, которое инициализируется в swing.disablevistaanimation имущество. Это поле определяет, является ли paintSkin метод вызывает skin.paintSkinRaw метод, если анимация отключена или же начинает попадать в анимацию.

Он работает на моем ноутбуке с Windows 8.1 с Java 8 (jdk1.8.0_65), поэтому его действие не ограничивается только Windows Vista.

Другие вопросы по тегам