如何创建一个出现在程序最顶部的 Swing 菜单栏?

How can I create a Swing menu bar that appears at the very top of my program?

编码语言:我正在使用 Swing 在 Kotlin 中编码,但如果您提供任何 Java 代码,我可以将其转码为 Kotlin。我知道 Kotlin 和 Java 所以我都能理解。此外,现阶段我正在使用 Swing 编写我的应用程序,没有库。

我想在应用程序的最顶部,在顶部栏中为我的应用程序创建一个菜单栏。我搜索了这个并找到了各种菜单栏教程,但每一个都导致了一个带有选项 below 的栏,应用程序图标和应用程序最小化、最大化和关闭按钮。

连官方的Java Documentation on the matter也只有下图的结果。

还有很多其他教程,但它们都只展示了如何在应用程序实际顶部下方创建菜单栏。我以为这只是因为应用程序无法更改顶部栏上的内容,但后来我意识到 Chrome,我现在正在使用的应用程序,不只是显示标题、图标和三个纽扣。它有一个完整的标签系统。所有 Microsoft Office 应用程序都有顶部栏的额外按钮,尽管它们无论如何都有一个额外的菜单项栏。提供了一个屏幕截图,显示了一个自动保存按钮和一些额外的东西。 (我删除了我的详细信息)

我提供了 Jetbrains 的 IntelliJ IDEA 的屏幕截图,作为我希望我的外观的完美示例。据我所知,IntelliJ 是在没有库的 Swing 中编码的,所以无论他们做什么,都必须只用 Swing 就可以实现。我希望在最顶部的栏上有一堆选项,就像下面的屏幕截图一样。

以防万一我在说什么有任何歧义,我希望我的顶部栏,即带有关闭按钮、最大化和最小化按钮、图标和应用程序标题的栏也包括其他选项。在 IntelliJ 的案例中,包括文件、编辑、查看、导航等。根据我的应用程序的用途,我可能包括文件、保存、撤消、选项和帮助,所有这些都带有列表中 select 项的下拉菜单. (例如,将鼠标悬停在文件上后,可能会在下拉菜单中显示“打开”、“打开最近”、“新建”、“设置”等)

任何有关如何执行此操作的链接将不胜感激。同样,我正在用 Kotlin 编写我的项目,但我也知道 Java 所以我会从两者那里得到答案。

SwingJFrametop bar 称为 title bar。它是 JFramedecorations 的一部分。 JFrame的边框也是装饰的一部分。

你能做的就是去掉装饰。然后菜单栏将显示为 顶部栏。移除装饰是通过调用方法 setUndecorated(true) 来实现的。删除装饰也意味着 JFrame 不能移动或调整大小,因为它没有边框或标题栏。因为没有标题栏,所以也没有可以单击以关闭 JFrame 的 X 按钮。您可以添加允许您移动和调整 JFrame 大小的代码,但我认为这不在您的问题范围内。在任何情况下,如果与您相关,您都会在 Internet 上找到有关如何执行此操作的示例。尽管如此,您仍然可以通过键盘按 Alt+F4 键关闭 JFrame

这是一个小型 Swing 应用程序,它显示一个空的、未修饰的 JFrame,其中有一个菜单。

import java.awt.Color;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.UIManager;
import javax.swing.WindowConstants;

public class MenuTest implements Runnable {
    private JFrame frame;

    public void run() {
        createAndShowGui();
    }

    private void createAndShowGui() {
        frame = new JFrame();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setJMenuBar(createMenuBar());
        frame.setSize(400, 350);
        frame.setUndecorated(true);
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    private JMenu createEditMenu() {
        JMenu editMenu = new JMenu("Edit");
        JMenuItem cutItem = new JMenuItem("Cut");
        editMenu.add(cutItem);
        JMenuItem copyItem = new JMenuItem("Copy");
        editMenu.add(copyItem);
        JMenuItem pasteItem = new JMenuItem("Paste");
        editMenu.add(pasteItem);
        return editMenu;
    }

    private JMenu createFileMenu() {
        JMenu fileMenu = new JMenu("File");
        JMenuItem newItem = new JMenuItem("New");
        fileMenu.add(newItem);
        JMenuItem openItem = new JMenuItem("Open");
        fileMenu.add(openItem);
        JMenuItem saveItem = new JMenuItem("Save");
        fileMenu.add(saveItem);
        return fileMenu;
    }

    private JMenuBar createMenuBar() {
        JMenuBar menuBar = new JMenuBar();
        menuBar.add(createFileMenu());
        menuBar.add(createEditMenu());
        return menuBar;
    }

    public static void main(String[] args) {
        UIManager.put("MenuBar.background", Color.LIGHT_GRAY);
        EventQueue.invokeLater(new MenuTest());
    }
}

Abra的答案本质上就是你想要的。但请注意,通过删除应用程序的装饰,您将失去本机功能!

  • 例如on Windows aero snap、任务栏预览等将被禁用。

并且应用程序不再是跨平台的:

  • 您将需要根据操作系统提供不同的标题栏实现。
  • 强制菜单栏位于 window 有违设计 macOS 应用程序的方法。

与其自己实现所有内容,不如查看 Darklaf 外观和感觉,它可以在不丢失本机功能或跨平台视觉效果的情况下实现您想要的效果。 (免责声明:我是它的创造者)

Look and Feel flatlaf 以最小的努力几乎完美地重建了所有级别的 IntelliJ 界面。

https://www.formdev.com/flatlaf/

System.setProperty( "flatlaf.menuBarEmbedded", "false" ); 将嵌入菜单栏。

这不仅仅是嵌入菜单栏,但如果您希望创建整体更现代的应用程序,这可能是您正在寻找的解决方案。