3

この質問は、この質問のフォローアップです。

JMenuBar動作が Firefox や iTunes のメニュー バーに似ている があります。つまり、メニュー バーは最初は非表示ですが、 を押すAltとメニュー バーが表示されます。

他の質問への回答は、その機能を実現する問題を解決しましたが、の問題を引き起こしました:が表示JMenuItemされていない場合、アクセラレータは機能しJMenuBarません。つまり、 (インストールされたアクセラレーター) が機能するAlt前に押す必要があります。CTRL+F

ただし、setAccelerator()メソッドには次のように記載されているため、これは当てはまりません。

public void setAccelerator(KeyStroke keyStroke)

メニュー階層を移動せずにメニュー項目のアクション リスナーを呼び出すキーの組み合わせを設定します。正しいアクションをインストールするのは UI の役割です。キーボード アクセラレータを入力すると、メニューが現在表示されているかどうかに関係なく機能することに注意してください。

それで、これは別の Java バグなのだろうか?

SSCCE (メニューを表示するには、 を押しますAlt。インストールされているアクセラレータはCTRL+F「検索」JOptionPane用で、入力用のダミーが表示されます):

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.KeyStroke;
import javax.swing.MenuElement;
import javax.swing.MenuSelectionManager;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.WindowConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class MenuBarTest extends JFrame {

    public MenuBarTest() {
        JMenu jMenu1 = new JMenu();
        JMenu jMenu2 = new JMenu();
        final JMenuBar jMenuBar1 = new JMenuBar();
        JMenuItem jMenuItem1 = new JMenuItem();
        JMenuItem jMenuItem2 = new JMenuItem();

        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        jMenu1.setText("File");
        jMenuItem1.setText("jMenuItem1");
        jMenu1.add(jMenuItem1);
        jMenuBar1.add(jMenu1);
        jMenu2.setText("Edit");
        jMenuItem2.setText("Find");
        jMenu2.add(jMenuItem2);
        jMenuBar1.add(jMenu2);
        setJMenuBar(jMenuBar1);

        jMenuBar1.setVisible(false);
        ChangeListener listener = new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                MenuElement[] elements = MenuSelectionManager.defaultManager().getSelectedPath();
                jMenuBar1.setVisible(elements.length > 0 && elements[0] == jMenuBar1);
            }
        };
        MenuSelectionManager.defaultManager().addChangeListener(listener);

        jMenuItem2.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F, java.awt.event.InputEvent.CTRL_MASK));
        jMenuItem2.setText("Find");
        jMenuItem2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                String what = JOptionPane.showInputDialog(MenuBarTest.this, "Search for what?");
                System.out.println(what);
            }
        });

        pack();
        setSize(500,500);
        setLocationRelativeTo(null);
        setVisible(true);
    }

    public static void main(String args[]) {
        try {
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
            ex.printStackTrace();
        }
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new MenuBarTest();
            }
        });
    }
}
4

1 に答える 1

4

あなたの強調を注意深く読んでください

キーボード アクセラレータを入力すると、メニューが現在表示されているかどうかに関係なく機能することに注意してください。

これは、親ではなくメニューについて話します。メニューが現在表示されていない可能性があることを意味します。それにもかかわらず、実際の (おそらく十分に文書化されていない) 決定的な特性は、それが表示されているに違いないということです。以前の質問に対する私の回答を更新しました。

于 2013-08-09T21:02:47.680 に答える