Создание закадрового кадра в Java (или: как избежать пустого меню на Mac, когда все окна приложений закрыты)?

Я создаю приложение для Mac и хочу, чтобы моя строка меню выглядела правильно.

Любой пользователь Mac знает, что строка меню должна находиться в меню верхнего экрана. Установка apple.laf.useScreenMenuBar на true в файле списка свойств избавляет от полосок меню в кадре и перемещает строку меню текущего окна с фокусом в экранное меню.

Однако, когда все окна скрыты или когда нет окон, нет полос меню, которые можно было бы переместить вверх, и вы просто получаете пустое меню. Я слышал, что решением этой проблемы было создание закадрового окна, которое сфокусировано, когда другие не сфокусированы. Единственная цель его - меню, чтобы его можно было заполнить, когда остальные уйдут.

Однако у меня было много проблем. Кажется, я не могу сдвинуть окно с экрана, потому что Mac не позволяет вам устанавливать координаты на что-то большее, чем размер экрана; вместо этого он просто отрезает его и помещает на край. Есть ли что-то еще, что мне нужно сделать, чтобы сделать окно за кадром?


person Community    schedule 02.02.2010    source источник


Ответы (6)


Вам обязательно стоит принять во внимание очень полезный ответ WizardOfOdds. Использование "Меню приложения", а настроить минимальный _ 1_, чтобы начать работу. Постоянное File меню позволит вашему приложению открывать новое окно, когда другие закрываются. Этот ответ ссылается на простой пример.

Хотя Руководство по человеческому интерфейсу являются отличным руководством к тому, чего ожидают ваши пользователи, вы, безусловно, можете поэкспериментировать с подходом, который вы предложили в своем вопросе. В частности, вы можете попробовать 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);
            }
        });
    }
}
person trashgod    schedule 03.02.2010
comment
Как и задающий вопрос, я не понимаю, чем может помочь статья, на которую ссылается WizardOfOdds. Кроме того, у человека, задающего вопрос, похоже, есть конкретная проблема: Кажется, я не могу убрать окно с экрана, потому что Mac не позволяет вам устанавливать координаты на что-то большее, чем размер экрана - person Arjan; 03.02.2010
comment
@Arjan: спасибо за редактирование; как вы получили более конкретную ссылку? Статья отсылает читателя к примерам Xcode в /Developer/Examples/Java. Я добавил пример перемещения окна за пределы экрана. - person trashgod; 03.02.2010
comment
Я только что выполнил элемент Inspect для заголовка в моем браузере и обнаружил привязку: <a name="//apple_ref/doc/uid/TP40001909-211936" [..]>. (Некоторые другие веб-страницы указывают идентификатор для каждого заголовка, и идентификаторы также могут использоваться для якорей.) (Кстати, хороший пример.) - person Arjan; 03.02.2010
comment
Этот ответ бесполезен; потому что невидимый фрейм не может иметь строку меню. Цель состоит в том, чтобы панель меню была видимой, когда нет видимых окон. - person Jesse Barnum; 01.03.2013
comment
Это делают приложения Mac, так что это неудивительно. Интересно, может ли JDesktopPane быть альтернативой. - person trashgod; 01.03.2013

Я знаю, что этот пост довольно старый, в любом случае у меня была та же проблема, и я нашел решение. На самом деле это довольно просто. Просто не добавляйте JMenuBar в основной фрейм при работе в Mac OS X, а в свое приложение, используя

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

Теперь MenuBar все еще отображается, даже если вы установите для видимости всего фрейма значение false.

person Pete    schedule 10.08.2012

Не прямое решение, но я думаю, что некоторые вместо этого создают окно размером в 1 пиксель. Однако это вызывает жалобы, подобные описанной у суперпользователя: Хаотичное поведение битого пикселя на моем iMac 24 " ...

person Arjan    schedule 02.02.2010
comment
Интересная статья, но мне не хватает связи. - person trashgod; 03.02.2010
comment
Я думаю, что связь заключается в том, что если вы создадите видимое окно 1x1, то для некоторых это может выглядеть как хаотичный битый пиксель, потому что, если он виден, он находится на экране (в отличие от setVisible (false), который может быть расположен за пределами экрана). - person SyntaxT3rr0r; 03.02.2010
comment
Ах, пиксель опоссума, просто прикидывается мертвым :-) - person trashgod; 03.02.2010
comment
Что ж, все остальные ответы просто сбили меня с толку, поэтому я попробовал это. Макинтоши тоже ограничивают размер окон! Я не уверен, что это не позволит мне сделать окно меньше высоты строки заголовка и ширины от 50 до 100 пикселей. Я чувствую себя таким глупым, судя по всем другим ответам, похоже, что решение, вероятно, прямо передо мной, но я его не вижу ... Это так сложно программировать, когда тебе четырнадцать ... Или, может быть, я просто отстой . - person ; 10.02.2010

Сначала примечание: ваш вопрос, похоже, действительно таков: «Как иметь меню« Окно »в соответствии с рекомендациями Apple Human Interface Guidelines», а не «создание закадрового кадра в Java», что кажется чудовищным взломом.

Я предлагаю проверить "Mac OS X от Apple Интеграция для Java ", который в разделе" Window menu", очевидно, точно показывает, чего вы пытаетесь достичь:

Рекомендации Apple Human Interface Guidelines предполагают, что все приложения Mac OS X должны иметь меню «Окно» для отслеживания всех открытых в данный момент окон. Меню «Окно» должно содержать список окон с галочкой рядом с активным окном.

person SyntaxT3rr0r    schedule 02.02.2010
comment
Эй ... Эм ... Ты действительно читал мой вопрос? Я как бы спросил, как обойти проблему, когда экранное меню исчезает, когда в Java не открыты никакие окна ... Я вообще ничего не сказал о руководящих принципах Apple Human Interface Guidelines. - person ; 02.02.2010
comment
По этой ссылке: Удаление меню из окон и размещение их в строке меню настоятельно рекомендуется, но этот подход не идеально имитирует собственный опыт работы с меню Mac OS X. В Mac OS X строка меню собственного приложения всегда видна, когда приложение является активным приложением, независимо от того, открыты ли какие-либо окна в данный момент. В Java для Mac OS X меню в строке меню связаны с фреймом верхнего уровня, и меню исчезают, если фрейм закрывается. - person Arjan; 03.02.2010
comment
Арджан, я знаю, это моя проблема, мне нужно создать окно, которое люди не видят, чтобы держать меню. - person ; 03.02.2010

Это комментарий к ответу trashgod. Он слишком большой, поэтому мне нужно переместить его сюда>. ‹


Больше проблем!

Я получаю 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]

Он перемещает его назад, когда он снова становится видимым!

Я искал целую вечность и ничего не нашел.

person Community    schedule 03.02.2010
comment
Это ожидаемое поведение. Я отредактировал свой ответ и добавил ссылку на простой, независимый от платформы пример, который может вам помочь. Кроме того, вы можете отредактировать свой вопрос, включив в него новые результаты. - person trashgod; 03.02.2010

Этот код работает в 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) в своем приложении, так что вам не нужно вызывать setJMenuBar () для каждого JFrame.

person Jesse Barnum    schedule 01.03.2013