6

我正在制作一个 Mac 应用程序,我希望我的菜单栏看起来正确。

任何 Mac 用户都知道菜单栏应该在顶部屏幕菜单中。在属性列表文件中设置apple.laf.useScreenMenuBartrue去掉框架内的菜单栏,并将当前焦点窗口的菜单栏移动到屏幕菜单。

但是,当所有窗口都被隐藏或没有窗口时,没有菜单栏可以移动到顶部,您只会得到一个空白菜单。我听说解决这个问题的方法是创建一个屏幕外窗口,当没有其他人关注时它会聚焦。它的唯一目的是它的菜单,以便在其他人离开时它可以填写。

但是,我遇到了很多问题。我似乎无法将窗口从屏幕上移开,因为 Mac 不允许您将坐标设置为超出屏幕大小的位置。它只是将其切断并将其定位在边缘。我还需要做些什么来制作屏幕外窗口吗?

4

6 回答 6

4

您绝对应该考虑 WizardOfOdds 的非常有用的答案。正确使用“应用程序菜单”会有所帮助,并且很容易设置一个最小Info.plist的开始。持久File菜单将允许您的应用程序在其他窗口关闭时打开一个新窗口。这个答案链接到一个简单的例子

尽管 Apple 的人机界面指南是用户期望的极好指南,但您当然可以尝试您在问题中建议的方法。特别是,您可以尝试setLocation(Short.MIN_VALUE, Short.MIN_VALUE)使用隐形窗口。此外,WindowEvent如果它表示最后一个可见窗口的关闭,您可能希望以某种特殊方式响应它。

附录:当您的侦听器看到最后一个可见窗口关闭时,创建一个新的空应用程序窗口。或者,在屏幕上移动不可见窗口并使其可见,直到用户决定如何继续。

附录:Mac OS X 有助于防止可见窗口窗体被移出屏幕,但很容易将不可见窗口置于边缘,如下所示。

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JToggleButton;

public class FrameTest extends JFrame {

    private static FrameTest marco;
    private static FrameTest polo;

    private static class MyPanel extends JPanel {

        public MyPanel() {
            super(true);
            final JToggleButton b = new JToggleButton("Test");
            b.addItemListener(new ItemListener() {
                @Override
                public void itemStateChanged(ItemEvent e) {
                    if (b.isSelected()) {
                        polo.setLocation(100, 100);
                        polo.setVisible(true);
                    }
                    else {
                        polo.setVisible(false);
                        polo.setLocation(Short.MIN_VALUE, Short.MIN_VALUE);
                    }
                }
            });
            this.add(b);
        }
    }

    public FrameTest(String title) {
        super(title);
        this.setLayout(new BorderLayout());
        this.add(new MyPanel());
        this.pack();
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public static void main(final String[] args) {

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                marco = new FrameTest("Marco");
                marco.setLocationRelativeTo(null);
                marco.setVisible(true);
                polo = new FrameTest("Polo");
                polo.setLocation(Short.MIN_VALUE, Short.MIN_VALUE);
            }
        });
    }
}
于 2010-02-03T00:57:23.450 回答
1

我知道这篇文章很老了,无论如何,我遇到了同样的问题并找到了解决方案。其实很简单。在 mac os x 上运行时不要将JMenuBar 添加到主框架,而是使用

com.apple.eawt.Application.getApplication().setDefaultMenuBar(menuBar);

现在即使您将所有框架的可见性设置为 false,MenuBar 仍会显示。

于 2012-08-10T17:11:50.883 回答
0

不是直接的解决方案,但我认为有些人会创建一个 1 像素的窗口。不过,这会产生一些抱怨,就像超级用户中描述的那样:我的 iMac 24" 上坏点的混乱行为......

于 2010-02-02T22:08:13.780 回答
0

此代码适用于 Java 7:

if( isMac ) {
    //This creates an invisible frame so that we always have a menu bar visible
    JFrame menuFrame = new JFrame();
    menuFrame.setUndecorated( true );
    menuFrame.setJMenuBar( defaultMenuBar );
    AWTUtilities.setWindowOpaque( menuFrame, false );
    menuFrame.setBounds( 0,0,1,1 );
    menuFrame.setVisible( true );
}

只需在打开任何其他窗口之前调用它,它就会留在后台并在其他窗口关闭时自动成为焦点窗口。您仍然可以在应用程序中使用 com.apple.eawt.Application.getApplication().setDefaultMenuBar(menuBar) 方法,这样您就不需要在每个 JFrame 上调用 setJMenuBar()。

于 2013-03-01T16:37:40.840 回答
0

首先要注意:您的问题似乎真的是“如何按照 Apple 人机界面指南创建窗口菜单”,而不是“在 Java 中创建屏幕外框架”,这似乎是一个可怕的 hack。

我建议检查 Apple 的“ Mac OS X Integration for Java ”,在“窗口菜单”下,它显然准确地显示了您想要实现的目标:

Apple 人机界面指南建议所有 Mac OS X 应用程序都应该提供一个窗口菜单来跟踪所有当前打开的窗口。一个窗口菜单应该包含一个窗口列表,在活动窗口旁边有一个复选标记。

于 2010-02-02T18:06:43.477 回答
0

这是对垃圾神回答的评论。它太大了,所以我必须把它移到这里>.<


更多问题!

我收到 2 个错误:

line 23: The method itemStateChanged(ItemEvent) of type new ItemListener(){} must override a superclass method

line 50:The method run() of type new Runnable(){} must override a superclass method

有什么帮助吗?我以前从未遇到过这种情况。我不知道这意味着什么。

编辑:我有更多的问题!我需要屏幕外窗口在屏幕外时可见,以便生成一个移动到屏幕菜单栏的菜单。当我使用代码时

offScreen = new JFrame("WTF?!  You can see me?");
offScreen.setSize(400,300);
offScreen.setLocation(0, java.awt.Toolkit.getDefaultToolkit().getScreenSize().height+50);
System.out.println(offScreen.getLocation());
offScreen.setVisible(true);
System.out.println(offScreen.getLocation());

我得到输出:

java.awt.Point[x=0,y=1100]
java.awt.Point[x=0,y=961]

一旦它再次可见,它就会将其移回!

我已经搜索了很长时间,但找不到任何东西。

于 2010-02-03T17:16:07.387 回答