2013-04-23 2 views
2

Я знаю, что есть метод SwingUtilities.updateComponentTreeUI(Component c), но он не работает отлично. Например, у меня есть JFileChooser, и текущий вид - это Windows, затем я меняю внешний вид на Nimbus с помощью SwingUtilities.updateComponentTreeUI(mainWindow), а стиль главного окна изменяется правильно, но когда я показываю выбор файла с помощью метода JFileChooser.showOpenDialog(Component parent), это все еще в ОС Windows. То же самое происходит, если я покажу всплывающее диалоговое окно с методом JPopupMenu.show(Component invoker, int x, int y). Любое решение этой проблемы?Как изменить внешний вид swing applicaiton во время выполнения?

+0

Чтобы быть ясно, вы также скорректировали ток L & F с [ 'UIManager.setLookAndFeel()'] (http://docs.oracle.com/javase/7/docs/ апи/javax/качели/UIManager.html # setLookAndFeel% 28java.lang.String% 29)? –

+0

Конечно, я сделал! –

ответ

5

Вызов SwingUtilities.updateComponentTreeUI(mainWindow) будет обновлять компоненты Swing только в иерархии Swing под mainWindow.

Если вы храните JFileChooser где-то в своем коде (например, в поле класса), не показывая JFileChooser, выбор не будет обновляться вызовом SwingUtilities.updateComponentTreeUI(mainWindow). Вы можете обойти это, добавив слушателя к UIManager себе и вызовите SwingUtilities.updateComponentTreeUI(myStoredFileChooser) от этого слушателя, когда внешний вид будет изменен.

Удостоверьтесь, что вы не создаете утечку памяти с этим, например. пусть что слушатель имеет WeakReference к JFileChooser только (как время жизни UIManager равно время жизни JVM)

+0

Как добавить слушателя в 'UIManager'? –

+0

Отличная работа по выделению 'WeakReference'. –

+0

@ ZhaoYi вы даже потрудились открыть javadoc класса 'UIManager'. В этом случае я уверен, что вы нашли бы ['addPropertyChangeListener'] (http://docs.oracle.com/javase/7/docs/api/javax/swing/UIManager.html#addPropertyChangeListener (java.beans.PropertyChangeListener)) метод – Robin

4

Если предположить, что value этого имя класса нового внешнего вида и ощущение, вот фрагмент кода для обновления все окна и суб-компоненты:

public static void updateLAF(String value) { 
    if (UIManager.getLookAndFeel().getClass().getName().equals(value)) { 
     return; 
    } 
    try { 
     UIManager.setLookAndFeel(value); 
     for (Frame frame : Frame.getFrames()) { 
      updateLAFRecursively(frame); 
     } 
    } catch (ClassNotFoundException e) { 
     e.printStackTrace(); 
    } catch (InstantiationException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (IllegalAccessException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (UnsupportedLookAndFeelException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

public static void updateLAFRecursively(Window window) { 
    for (Window childWindow : window.getOwnedWindows()) { 
     updateLAFRecursively(childWindow); 
    } 
    SwingUtilities.updateComponentTreeUI(window); 
} 
+0

Это не поможет, если вы кешируете компонент Swing, который не является частью иерархии Swing в вашем собственном коде. – Robin

+0

@Robin Действительно, хороший улов для кэшированных компонентов. Тем не менее, если он встроен в другой компонент, который является иерархией, другой вариант заключается в переопределении 'updateUI', вызове' super.updateUI', а также переадресации вызова в файл-выбор. –

+0

Я знаю это благодаря опыту. Уже потратьте некоторое время на эту проблему в моем собственном коде. Обычно для выбора файла он не содержится в иерархии, но только открывается в диалоговом окне при необходимости – Robin

Смежные вопросы