Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何更改Swing应用程序&x27;s运行时的外观和感觉?_Java_Swing_User Interface_Look And Feel - Fatal编程技术网

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创建的,因此我无法获得它们的引用。