4

これで、JMenu とその中にいくつかの JMenuItems ができました。JMenu と JMenuItem の状態が「選択済み」に変更されたときに、プログラムに何らかのアクションを実行させたいと考えています。ユーザーがキーボードを使用してメニュー内を移動できるようにするため、MouseLitener の MouseOver は使用しません。今、私はこのリスナーを書きました:

class MenuItemListener implements ChangeListener {
    @Override
    public void stateChanged(ChangeEvent arg0) {
        JMenuItem item = (JMenuItem) arg0.getSource();
        if(item.isSelected())
            System.out.println(item.getText()+" pressed!");
    }
}

このリスナーを JMenu に追加すると正常に動作しますが、JMenuItem に追加しても何も起こりません... if ステートメントを削除してリスナーが両方に反応するようにすると、メニューが選択されている場合と選択解除されている場合に、JMenu と同様に正常に動作しますJMenuItem 用。ご覧のとおり、JMenuItem は isSelected() テストを「パス」できません...しかし、何が問題になるのでしょうか? :S

4

2 に答える 2

7

いかなる方向への攻撃も意図していません。これは歴史のある質問の 1 つに過ぎません。

  • 初期要件: マウスが JMenuItem の上にあるときに何かをする
  • みなさんのイニシャル: MouseListener
  • 最初の逸脱した提案 (@mKorbel に敬意を表します!): buttonModel の ChangeListener、rollover プロパティのチェック

  • 洗練された要件: キーボードとマウスの両方で、JMenuItem が強調表示されたときに doSomething。

  • 洗練された最愛の人: buttonModel の ChangeListener、プロパティが指定されていません
  • 洗練された逸脱: ActionListener

  • 現在の要件: JMenu または JMenuItem の "selected" プロパティが変更されたときの doSomething。

  • 現在の最愛の人: リスナーでは実行できません。オーバーライド...
  • 現在の偏差: Action、MenuListener ...

正確で完全な (ただし、後から考えると、キーボードについてはまだ言及されていないため) 回答は、最初のラウンドで既に利用可能でした: 状態の変化をキャプチャするのに十分な「低レベル」のセマンティック リスナー (候補は、ロールオーバー、武装、選択され、buttonModel レベルで押された場合)、menuItems の強調表示された状態を変更します。残念ながら、正確な関係は (少なくとも私には) よく知られておらず、文書化されておらず (読んでください: 怠惰な私はざっと見ても何も見つかりませんでした)、ロールオーバーは常に false であるため (これもまた私にとって) 混乱を招くことさえあります (?)。メニューアイテム用

実験者の反応は .. 試してみることです: 以下は、いくつかのメニュー ツリーの状態の変化をリッスンしてログに記録するコード スニペットです (単純に任意のメニュー バーにスローし、マウスを動かしてキーボードでナビゲートします)。

勝者は次のとおりです。 - ChangeListener を使用して、ソースが選択されているか準備されているかを確認します。

    ChangeListener ch = new ChangeListener() {

        @Override
        public void stateChanged(ChangeEvent e) {
            if (e.getSource() instanceof JMenuItem) {
                JMenuItem item = (JMenuItem) e.getSource();
                if (item.isSelected() || item.isArmed()) {
                    System.out.println("Highlighted: " + item.getActionCommand());
                }
            }
        }
    };

キーボードとマウスの両方、JMenu と JMenuItem の両方で動作します

//----------- code snippet to track property changes in menuItem/buttonModel

    // test menu
    JMenu menu = new JMenu("Sample menu");
    menu.setMnemonic('s');
    installListeners(menu);

    // first menuitem
    JMenuItem other = menu.add("content1");
    installListeners(other);
    // second menuitem
    other = menu.add("again + ");
    installListeners(other);

    // sub
    JMenu sub = new JMenu("subMenu");
    installListeners(sub);
    menu.add(sub);

    // menus in sub
    other = sub.add("first in sub");
    installListeners(other);
    other = sub.add("second in sub");
    installListeners(other);

    getJMenuBar().add(menu);

private void installListeners(JMenuItem menu) {
    menu.getModel().addChangeListener(getChangeListener());
    menu.addChangeListener(getChangeListener());
}

private ChangeListener getChangeListener() {
    ChangeListener ch = new ChangeListener() {

        @Override
        public void stateChanged(ChangeEvent e) {
            if (e.getSource() instanceof ButtonModel) {
                ButtonModel model = (ButtonModel) e.getSource();
                System.out.println("from model: " + createStateText(model));
            } else if (e.getSource() instanceof JMenuItem) {
                JMenuItem item = (JMenuItem) e.getSource();
                System.out.println("  from item: " + createStateText(item));
            }
        }

        private String createStateText(ButtonModel model) {
            String text = model.getActionCommand() + " armed: " + model.isArmed();
            text += " selected: " + model.isSelected();
            text += " rollover " + model.isRollover();
            text += " pressed: " + model.isPressed();
            return text;
        }

        private String createStateText(JMenuItem model) {
            String text = model.getActionCommand() + " armed: " + model.isArmed();
            text += " selected: " + model.isSelected();
            // not supported on JMenuItem nor on AbstractButton
           // text += " rollover " + model.isRollover();
           // text += " pressed: " + model.isPressed();
            return text;
        }
    };
    return ch;
}
于 2011-05-12T10:00:30.993 に答える