2015-11-26 35 views
2

我目前正在研究一個項目,該項目需要在更新查看記錄時更改JRadioButton的狀態。JRadioButton選擇不會顯示在GUI上,直到在Windows中可見L&F

我們有幾個客戶抱怨說,當記錄發生變化時,如果JRadioButton不在屏幕上,它將不會更新,直到屏幕顯示。這種行爲似乎是使用Windows Look &感覺的結果,因爲它沒有設置時似乎不會發生。

下面的代碼示例演示了這一點。 默認選擇的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 
     } 
    } 
} 

是否有辦法防止這種行爲,甚至加快步伐,使之成爲我們的用戶不太明顯?

+0

觀察:只有選定的組件可見(所有其他選項卡組件都是「隱藏的」('setVisible(false)'),這意味着它們不會響應繪製請求,很好而且高效。 ,當它們變得可見時,它們必須在那裏重新繪製狀態,在這種情況下,從被選中到未選中,反之亦然 - 這似乎是問題,解決方案可能有點複雜 – MadProgrammer

+0

我認爲這可能會一直是這種情況,但不確定,因爲標準的外觀和感覺沒有表現出相同的行爲......可能是因爲Windows的'感覺'具有與標準相反的過渡效果。 – Kuronai

+0

Windows L&F是唯一一個(我可以找到),它有「取消選擇」動畫,這實際上是這個問題的一個副作用,所以當組件變得可見時,單選按鈕會從之前的狀態到那裏新的狀態,但由於Windows L&F中的動畫,它真的很明顯的狀態變化 – MadProgrammer

回答

0

您可能能夠通過指定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。

+0

我已經接受因爲這是我們最終讓受影響的客戶做的答案,因爲看起來好像壓制動畫所需的努力太大了,沒有理由(感謝MadProgrammer對他的幫助)。 – Kuronai