web-dev-qa-db-ja.com

Javaスイングポップアップメニューとjlist

ここに私の問題があります:私はjListとポップアップメニューを持っています。 jListを右クリックすると、ポップアップメニューが表示されます。問題は、マウスが指しているjListアイテムが選択されないことです。そして、私はそれをしてもらいたいのです。リスト内の項目にカーソルを合わせて右ボタンを押すと、2つのことが起こります。クリックした項目を選択して、ポップアップメニューを表示します。

私はこれを試しました:

jLists.addMouseListener(new MouseAdapter() {

     @Override
     public void mousePressed(MouseEvent e) {
            jList.setSelectedIndex(jList.locationToIndex(e.getPoint()));
     }
});

jList.setComponentPopupMenu(jPopupMenu);

ただし、ポップアップメニューのみが表示されます。この行を削除した場合:

jList.setComponentPopupMenu(jPopupMenu);

次に、右クリックで選択が機能します(ただし、ポップアップメニューは表示されません)。

では、これら2つの機能(両方)を機能させるための最良の方法は何だと思いますか?

私の英語に感謝し、申し訳ありません。

21
VaclavDedik

setComponentPopupMenuは行わないでください。 MouseAdapterで次の手順を実行します。

public void mousePressed(MouseEvent e)  {check(e);}
public void mouseReleased(MouseEvent e) {check(e);}

public void check(MouseEvent e) {
    if (e.isPopupTrigger()) { //if the event shows the menu
        jList.setSelectedIndex(jList.locationToIndex(e.getPoint())); //select the item
        jPopupMenu.show(jList, e.getX(), e.getY()); //and show the menu
    }
}

これはうまくいくはずです。

EDIT:一部のプラットフォームではマウスを押すとポップアップが表示されるため、コードはpressイベントとreleaseイベントの両方をチェックするようになりました。その他のリリース時。詳細については、 Swingチュートリアル を参照してください。

27
Alba Mendez

引き続きsetComponentPopupMenuを使用する場合(クロスプラットフォームの方法でポップアップのマウスとキーボードの呼び出しを処理するので便利です)、JPopupMenu.show(Component, int, int)をオーバーライドして適切な行を選択できます。

JPopupMenu jPopupMenu = new JPopupMenu() {
    @Override
    public void show(Component invoker, int x, int y) {
        int row = jList.locationToIndex(new Point(x, y));
        if (row != -1) {
            jList.setSelectedIndex(row);
        }
        super.show(invoker, x, y);
    }
};

jList.setComponentPopupMenu(jPopupMenu);

ポップアップがキーボードを介して呼び出された場合(ターゲットコンポーネントのgetPopupLocationもオーバーライドしない場合)、JPopupMenu.showで取得したx、yの位置がコンポーネントの中点になることに注意してください。 。この場合、すでに選択範囲がある場合は、選択範囲を変更したくないでしょう。

キーボードとマウスの呼び出しの問題を解決するために私が思いついた解決策は、コンポーネントのクライアントプロパティをgetPopupLocationのオーバーライドに設定し、ポップアップを表示するときにそれを確認することでした。キーボードから呼び出すと、getPopupLocationの引数はnullになります。これがコアコードです(おそらく、コンポーネントとそのポップアップメニューで使用できるユーティリティクラスに実装されています)。

private static final String POPUP_TRIGGERED_BY_MOUSE_EVENT = "popupTriggeredByMouseEvent"; // NOI18N

public static Point getPopupLocation(JComponent invoker, MouseEvent event)
{
    boolean popupTriggeredByMouseEvent = event != null;
    invoker.putClientProperty(POPUP_TRIGGERED_BY_MOUSE_EVENT, Boolean.valueOf(popupTriggeredByMouseEvent));
    if (popupTriggeredByMouseEvent)
    {
        return event.getPoint();
    }
    return invoker.getMousePosition();
}

public static boolean isPopupTriggeredByMouseEvent(JComponent invoker)
{
    return Boolean.TRUE.equals(invoker.getClientProperty(POPUP_TRIGGERED_BY_MOUSE_EVENT));
}

次に、コンポーネントのgetPopupLocationをオーバーライドします。

@Override
public Point getPopupLocation(MouseEvent event)
{
    return PopupMenuUtils.getPopupLocation(this, event);
}

JPopupMenu.showのオーバーライドでisPopupTriggeredByMouseEventを呼び出して、ポップアップ位置(または基になるコンポーネントにとって意味のあるアクション)で行を選択するかどうかを決定します。

JPopupMenu jPopupMenu = new JPopupMenu() {
    @Override
    public void show(Component invoker, int x, int y) {
        int row = jList.locationToIndex(new Point(x, y));
        if (row != -1 && PopupMenuUtils.isPopupTriggeredByMouseEvent((JComponent) invoker)) {
            jList.setSelectedIndex(row);
        }
        super.show(invoker, x, y);
    }
};
9
Rangi Keen