3

JMenuBar に関していくつか問題があり、それを理解できないようです。

問題の要約から始めましょう。プログラムは、JFrame、JDialog、および JMenuBar で構成されています。最初に、上部に JMenuBar がある JFrame が表示されます。しかし、ある時点で、ユーザーがいくつかのテキスト フィールドに入力できる JDialog がポップアップします。私が抱えている問題は、フォーカスが JDialog に移動するとすぐに、JMenuBar が消えることです。私が望むのは、プログラム全体がフォーカスされていない場合を除いて、JMenuBar が常に画面の上部にあることです。ここに 2 つのスクリーンショットがあります。最初のスクリーンショットでは JFrame が選択され、もう 1 つのスクリーンショットでは JDialog が選択されています。

ここに画像の説明を入力

ここに画像の説明を入力

したがって、私が実際に望んでいるのは、フォーカスが JFrame にあるときに JMenuBar だけを見るのではなく、常に JMenuBar を見たいということです。JDialogs は、JFrame のように JMenuBar を上部に配置できないため、複数の JMenuBars を配置するのではなく、常に表示される JMenuBars のみを配置することにしました。

最後に、可能な限り小さく (そしてまだ機能している) コードの一部を提供し、問題も含んでいます。

import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JRootPane;
import javax.swing.KeyStroke;

/**
 * @author Guus Leijsten
 * @created Oct 27, 2012
 */
public class MenuBarProblem extends JFrame {
    public MenuBarProblem() {
        super("Frame");
        this.setMinimumSize(new Dimension(270, 200));
        this.setPreferredSize(new Dimension(800, 530));
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);

        JRootPane root = this.getRootPane();
    //Menu
        JMenu fileMenu = new JMenu("File");
        JMenuItem file_exit = new JMenuItem("Exit");
        file_exit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
        file_exit.setToolTipText("Exit application");
        file_exit.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });
        fileMenu.add(file_exit);

        JMenuBar menu = new JMenuBar();
        menu.add(fileMenu);
        root.setJMenuBar(menu);

        this.setVisible(true);

        JDialog d = new JDialog(this, "Dialog");
        d.setSize(200, 100);
        d.setLocation(0, (int)root.getContentPane().getLocationOnScreen().getY());
        d.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        d.setVisible(true);
    }

    public static void main(String[] args) {
        String os = System.getProperty("os.name").toLowerCase();
        if(os.indexOf("mac") >= 0) {
            System.setProperty("apple.laf.useScreenMenuBar", "true");
        }
        new MenuBarProblem();
    }
}

正直に言うと、問題は JRootPane の部分にあると思います。しかし、わかります;)

他の誰かがこの問題に遭遇し、それを解決することができましたか、それとも試してみたい人はいますか?

前もって感謝します!


追加されたコンテンツ:

次の例では、プレイにいくつかの機能を提供するバージョンを示します。

これが私が作っているプログラムです: ここに画像の説明を入力 2番目の画像は、右のメニューをドッキング解除した状態です。 ここに画像の説明を入力 JMenuBar がないと、プログラムの多くの機能が無効になるため、明らかに JMenuBar は引き続き表示され、操作可能である必要があります。

この時点で、ダイアログ (ドッキング解除されたメニュー) がドッキング解除され、フォーカスされているときに JMenuBar が表示されたままになることは不可能であると考え始めています。

JDialog の JMenuBar を mac osx スタイル (画面の上部) にすることはできないので、ドッキング解除に使用できる他の手法はありますか?

4

2 に答える 2

2

この問題を解決する鍵の 1 つは、以下に示すように、キー バインドで共通のメニュー アクションを共有できるようにすることです。メニュー項目、ダイアログのコンテンツ、および (それ以外の場合は余分な) ボタンがすべて同じActionインスタンスを使用できることに注意してください。いくつかの追加メモ:

  • を使用していただきありがとうございgetMenuShortcutKeyMask()ます。

  • Swing GUI オブジェクトは、イベント ディスパッチ スレッド (EDT)でのみ構築および操作する必要があります。

  • システム プロパティは、EDT を開始する前に設定する必要があります。

  • ジオメトリが判明した、ダイアログsetLocation()をフレームに対して相対的に作成します。

  • 一般的な Mac のイディオムでは、次の述語を使用します。

    if (System.getProperty("os.name").startsWith("Mac OS X") {…}
    
  • このも参照してください。

  • ダイアログ自体でローカルに使用する場合は、 も検討してJToolBarください。

MenuBarメニューの問題

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.KeyStroke;

/**
 * @see https://stackoverflow.com/a/13100894/230513
 */
public class MenuBarProblem extends JFrame {

    private static final int MASK =
        Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
    private static final String exitName = "Exit";
    private static final KeyStroke exitKey =
        KeyStroke.getKeyStroke(KeyEvent.VK_W, MASK);
    private final ExitAction exitAction = new ExitAction(exitName);

    public MenuBarProblem() {
        super("Frame");
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);

        JMenu fileMenu = new JMenu("File");
        JMenuItem fileExit = new JMenuItem(exitAction);
        fileMenu.add(fileExit);
        JMenuBar menu = new JMenuBar();
        menu.add(fileMenu);

        JDialog d = new JDialog(this, "Dialog");
        JPanel p = new JPanel();
        p.getInputMap().put(exitKey, exitName);
        p.getActionMap().put(exitName, exitAction);
        p.add(new JButton(exitAction));
        d.add(p);
        d.pack();
        d.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);

        this.setJMenuBar(menu);
        this.pack();
        this.setSize(new Dimension(320, 240));
        this.setLocationByPlatform(true);
        this.setVisible(true);
        d.setLocation(this.getRootPane().getContentPane().getLocationOnScreen());
        d.setVisible(true);
    }

    private static class ExitAction extends AbstractAction {


        public ExitAction(String name) {
            super(name);
            this.putValue(Action.MNEMONIC_KEY, exitKey.getKeyCode());
            this.putValue(Action.ACCELERATOR_KEY, exitKey);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            System.exit(0);
        }
    }

    public static void main(String[] args) {
        System.setProperty("apple.laf.useScreenMenuBar", "true");
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new MenuBarProblem();
            }
        });
    }
}
于 2012-10-27T14:08:41.237 に答える
0

解決しました!

setAlwaysOnTop(true) を使用して JFrame を使用すると、フォーカスが変更されたときに JMenuBar を持つという望ましい効果が得られます。

于 2012-11-11T09:53:37.380 に答える