5

サブメニュー(JMenu)にアクセラレータを追加するユーザーリクエストがあります。これにより、ユーザーはショートカットを押して、対応するサブメニューを「展開」し、含まれているメニュー項目を表示できます。

私は、このようなもの(Javaまたは他の言語のいずれか)を見たすべての人を思い出しません。このアプリケーションは、Swingを使用してJavaで記述されています。正常に動作するアクセラレータを備えたJMenuItemがいくつかありますが、アクセラレータをJMenuに追加しようとすると、次の例外が発生します。

java.lang.Error:setAccelerator()がJMenuに対して定義されていません。代わりにsetMnemonic()を使用してください。

MenuDemoを使ってみました!これをもう少し実験するためのコード。

これは私が試したものです:

//a submenu
menu.addSeparator();
submenu = new JMenu("A submenu");
submenu.setMnemonic(KeyEvent.VK_S);
submenu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_U, InputEvent.CTRL_MASK));

最後の行は私が追加した行で、例外が発生します。

広範囲にわたるグーグルを試しましたが、JMenuItemにアクセラレータを追加する方法に関する記事しか見つかりません。

JMenuはこれをネイティブにサポートしていないようです。この動作を実現するための回避策はありますか?

4

2 に答える 2

7

もう1つのオプションは、アクセラレータのget / setをオーバーライドして、JMenuItemの動作を再現することです。その後、UIが残りの作業を行います。

重要なことは、プロパティの変更を実行し、アクセラレータの取得/設定を一貫させることです。このソリューションの利点は、ショートカット/アクセラレータの視覚的な表示も提供することです。

これが小さなデモコードです:

import java.awt.event.KeyEvent;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestMenu {

    protected void initUI() {
        JFrame frame = new JFrame(TestMenu.class.getSimpleName());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JMenuBar bar = new JMenuBar();
        JMenu topMenu = new JMenu("Top Menu");
        JMenu subMenu = new JMenu("Sub menu") {
            private KeyStroke accelerator;

            @Override
            public KeyStroke getAccelerator() {
                return accelerator;
            }

            @Override
            public void setAccelerator(KeyStroke keyStroke) {
                KeyStroke oldAccelerator = accelerator;
                this.accelerator = keyStroke;
                repaint();
                revalidate();
                firePropertyChange("accelerator", oldAccelerator, accelerator);
            }
        };
        subMenu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4, KeyEvent.CTRL_MASK));
        JMenuItem item1 = new JMenuItem("Item 1");
        JMenuItem item2 = new JMenuItem("Item 2");
        subMenu.add(item1);
        subMenu.addSeparator();
        subMenu.add(item2);
        topMenu.add(subMenu);
        bar.add(topMenu);
        frame.setJMenuBar(bar);
        frame.setSize(400, 300);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (UnsupportedLookAndFeelException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                new TestMenu().initUI();
            }
        });
    }

}
于 2012-10-16T10:54:35.087 に答える
6

そんなことはできないと思います。しかし、あなたができることはAbstractAction、クリックをシミュレートするを追加することです。

submenu.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("control U"), "expand");
    submenu.getActionMap().put("expand", new AbstractAction("expand") {
        private static final long serialVersionUID = 1L;

        @Override
        public void actionPerformed(ActionEvent evt) {
            submenu.doClick();
        }
    }
);

これがあなたにも役立つことを願っています。

于 2012-10-16T08:09:58.420 に答える