Создание закадрового фрейма в Java (или: как избежать пустого меню на Mac, когда все окна приложений закрыты)? - PullRequest
6 голосов
/ 02 февраля 2010

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

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

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

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

Ответы [ 6 ]

4 голосов
/ 03 февраля 2010

Вы должны обязательно рассмотреть очень полезный ответ 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);
            }
        });
    }
}
1 голос
/ 10 августа 2012

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

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

Теперь панель меню по-прежнему отображается, даже если для видимости всего кадра установлено значение false.

0 голосов
/ 01 марта 2013

Этот код работает в 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.

0 голосов
/ 03 февраля 2010

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


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

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

Он сдвигает его назад, как только он снова становится видимым!

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

0 голосов
/ 03 февраля 2010

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

0 голосов
/ 02 февраля 2010

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

Я предлагаю проверить « Интеграция Mac OS X для Java » от Apple, которая в разделе « Меню окна », по-видимому, точно показывает, чего вы пытаетесь достичь:

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

...