Java 如何更改Swing应用程序&x27;s运行时的外观和感觉?
我知道有一个Java 如何更改Swing应用程序&x27;s运行时的外观和感觉?,java,swing,user-interface,look-and-feel,Java,Swing,User Interface,Look And Feel,我知道有一个SwingUtilities.updateComponentTreeUI(ComponentC)方法,但它并不完美。例如,我有一个JFileChooser,当前的外观是Windows,然后我用SwingUtilities.updateComponentTreeUI(主窗口)将外观更改为Nimbus,主窗口的样式正确更改,但是当我用JFileChooser.showOpenDialog(组件父级)显示文件选择器时method,它仍在Windows的外观中。如果我使用jpopmpmen.
SwingUtilities.updateComponentTreeUI(ComponentC)
方法,但它并不完美。例如,我有一个JFileChooser
,当前的外观是Windows,然后我用SwingUtilities.updateComponentTreeUI(主窗口)
将外观更改为Nimbus,主窗口的样式正确更改,但是当我用JFileChooser.showOpenDialog(组件父级)显示文件选择器时
method,它仍在Windows的外观中。如果我使用jpopmpmen.show(Component invoker,int x,int y)
方法显示一个弹出对话框,也会发生同样的情况
此问题的任何解决方案?调用
SwingUtilities.updateComponentTreeUI(主窗口)
将仅更新mainWindow下Swing层次结构中的Swing组件
如果将JFileChooser
存储在代码中的某个位置(例如,在类的字段中),而不显示JFileChooser
,则调用SwingUtilities.updateComponentTreeUI(主窗口)
不会更新选择器。您可以通过向自己的UIManager
添加一个侦听器来解决此问题,并在外观更改时从该侦听器调用SwingUtilities.updateComponentTreeUI(myStoredFileChooser)
请确保您不会因此造成内存泄漏,例如,让该侦听器只对JFileChooser
进行WeakReference
(因为UIManager的生存期等于JVM的生存期)假设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);
}
为了清楚起见,您还使用?调整了当前的L&F,如果您在自己的代码中缓存一个不属于Swing层次结构的Swing组件,这将不会有帮助。@Robin确实,缓存组件的捕捉很好。但是,如果它嵌入到另一个组件(层次结构)中,另一个选项是覆盖updateUI
,调用super.updateUI
,并将调用转发给文件选择器。我知道这要归功于经验。我已经在自己的代码中花了一些时间来解决这个问题。通常,对于文件选择器,它不包含在层次结构中,而是仅在需要时在对话框中打开Window[]wins=Window.getWindows()
而不是'Window Window:frame.getOwnedWindows()`可以用于所有可以显示的容器,isDisplayable()
,isDisplayable(
)返回已删除的Rootpane
容器,或者如果DecorationsTyp
e以编程方式更改,则更新Window.getWindows()返回的所有窗口
不会影响我尚未在对话框中显示的文件选择器。如何将侦听器添加到UIManager
?突出显示WeakReference
@ZhaoYi的工作做得很好。您是否甚至懒得打开UIManager
类的javadoc。在这种情况下,我相信您会找到方法,正如我在下面所说的,一些组件可能是由第三方LIB创建的,因此我无法获得它们的引用。