在 Gnome 顶部栏中设置我的 Java Swing 应用程序标题的正确方法是啥?

Posted

技术标签:

【中文标题】在 Gnome 顶部栏中设置我的 Java Swing 应用程序标题的正确方法是啥?【英文标题】:What is the proper way to set my Java Swing application's title in the Gnome top bar?在 Gnome 顶部栏中设置我的 Java Swing 应用程序标题的正确方法是什么? 【发布时间】:2018-05-03 03:18:34 【问题描述】:

我正在使用以下代码在 Gnome 3 的顶部栏中设置我的 Java Swing 应用程序的标题。但是,当我运行它时,我会收到代码下方显示的警告。有没有更好的方法在代码中设置应用程序标题?请注意,这不是关于设置窗口本身标题的问题。

try

    Toolkit toolkit = Toolkit.getDefaultToolkit();
    Field awtAppClassNameField = toolkit.getClass().getDeclaredField("awtAppClassName");
    awtAppClassNameField.setAccessible(true);
    awtAppClassNameField.set(toolkit, "FNDice");

catch (NoSuchFieldException | IllegalAccessException e)

    e.printStackTrace();

这是我在运行应用程序时看到的警告。

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.gmail.fishnet37222.fndice.App (file:/home/dave/IdeaProjects/fndice/target/classes/) to field sun.awt.X11.XToolkit.awtAppClassName
WARNING: Please consider reporting this to the maintainers of com.gmail.fishnet37222.fndice.App
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

【问题讨论】:

它不起作用?给你的 JFrame 一个标题就够了吗? 当我使用我提供的代码时它可以工作。不过,它给了我这些警告。我的问题是,是否有一种方法可以设置应用程序标题,而无需求助于未来版本的 Java 可能不支持的黑客攻击。不,在 JFrame 上设置标题是不够的。 这些警告从 JDK9 开始。甲骨文不再允许自定义应用程序名称,而是追随他们的开发人员。 Java 已死。 @mariusm 似乎只是警告它不受支持的界面,可能是因为不能保证所有环境在其桌面环境中都显示“应用程序标题”。由于这是一个警告,并且 Project jigsaw (Java 9) 现在可以通过其模块系统强制执行 API 合同,因此该应用程序启动时可能没有允许非法模块访问的标志。 【参考方案1】:

这是我用来确定使用 Oracle 的 JDK 在 Ubuntu 上运行的 KDE 的应用程序名称。我知道没有方法可以覆盖该值,该值是从包含您的 main() 方法的 java 类中计算出来的。我还没有在其他窗口管理器或 OpenJDK 上测试过。如果您的 main() 方法在 com.foo.MyApp 中,那么您的应用名称将是“com-foo-MyApp”。

    /**
     * For Java 17, we can no longer access private fields, which means we can't override the "awtAppClassName" setting to control the
     * app name that the Linux window manager uses for window rules in Settings/Window Management/Window Rules.
     *
     * This code was copied from sun.awt.X11.XToolkit. It displays Window class (application) name needed to configure window rules
     */
    public static void displayMainClassName() 
        String mainClassName = null;
        StackTraceElement[] trace = (new Throwable()).getStackTrace();
        int bottom = trace.length - 1;
        if (bottom >= 0) 
            mainClassName = trace[bottom].getClassName();
        
        if (mainClassName == null || mainClassName.isEmpty()) 
            mainClassName = "AWT";
        
        mainClassName = mainClassName.replace('.', '-');
        System.out.println("mainClassName = " + mainClassName);
    

【讨论】:

【参考方案2】:

假设应用程序是使用 .desktop 文件启动的,则可以通过将 StartupWMClass 键添加到 .desktop 文件来解决此问题,例如:

StartupWMClass=com-example-Application

该值是应用程序主类的完全限定名称,其中的点由连字符代替。

如果您更喜欢破解 sun.awt.X11.XToolkit 类,您只需添加:

--add-opens=java.desktop/sun.awt.X11=ALL-UNNAMED

到命令行避免非法反射访问警告。

【讨论】:

【参考方案3】:

这是两种不同事物的副作用,通过反射使用非 API 接口,以及使用正在使用模块加载系统的新 JVM(在 Java 9 中引入)

使用 Java 模块,JAR 文件现在包含更多元数据,说明其他 JAR 文件应访问所包含代码的哪些部分。这允许许多以前只能通过 OSGI 或自定义类加载器才能实现的事情。

奇怪的是您正在使用的代码和您正在使用的库尚未更新以正确工作/与默认情况下强制执行的模块系统交互。要让遗留反射代码以向后兼容的方式访问非 API 入口点,您需要将命令行标志 --illegal-access=permit 添加到您的 java 启动命令中。

请注意,运行时启动和编译器启动可能都需要此操作,如果您同时执行这两项操作。

出于好奇,在这个平台上,jframe.setTitle("title") 不起作用,还是setTitle 之前的代码库可用?

【讨论】:

我也发现了同样的问题。并回答您的问题:我使用 JFrame.setTitle("A"),仍然在 Ubuntu 中,我可以看到一个以完全限定类名命名的顶部菜单。所以一个 setTitle() 是不够的。对于 OS X,有一个 JVM 开关 ***.com/questions/4007512/…

以上是关于在 Gnome 顶部栏中设置我的 Java Swing 应用程序标题的正确方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Android Kitkat 中设置我的短信应用默认值?

在 node.js 中设置我的 babel-watch 时遇到问题

如何在我的 winforms 应用程序中设置我的 datagrid 滚动条的位置?

如何在 Google App Engine 中设置我的默认版本

如何在 Visual Studio Code 中设置我的工作区文件夹?

如何在 VS2010 RC 中设置我的开发 Web 浏览器?