Подтвердить что ты не робот

Всплывающее меню Java swing и jlist

вот моя проблема: У меня есть jList и всплывающее меню. Когда я нажимаю правой кнопкой мыши на jList, появляется всплывающее меню. Проблема в том, что элемент jList, на который указывает мышь, не будет выбирать. И я хочу, чтобы это было так. Когда я нажимаю курсор на элемент в списке и нажимаю правую кнопку, я хочу, чтобы произошло две вещи. Выберите элемент, на который я щелкнул, и покажу всплывающее меню.

Я пробовал это:

jLists.addMouseListener(new MouseAdapter() {

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

jList.setComponentPopupMenu(jPopupMenu);

Но это только показывает всплывающее меню. Если я удалю эту строку:

jList.setComponentPopupMenu(jPopupMenu);

то работает щелчок правой кнопкой мыши (но всплывающее меню не отображается).

Итак, как вы думаете, лучший способ заставить эти две функции (оба) работать?

Спасибо и извините за мой английский.

4b9b3361

Ответ 1

Не выполняйте 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.

Ответ 2

Если вы хотите продолжать использовать 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 на целевом компоненте), то местоположение x, y, которое вы получаете в JPopupMenu.show, будет средой вашего компонента. Если в этом случае уже есть выбор, вы, вероятно, не захотите изменить выбор.

Решение, которое я придумал для решения проблемы с клавиатурой или вызовом мыши, состояло в том, чтобы установить свойство клиента в компоненте в переопределении 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);
}

и вызовите isPopupTriggeredByMouseEvent в переопределении JPopupMenu.show, чтобы определить, следует ли выбирать строку во всплывающем местоположении (или любое действие может иметь смысл для базового компонента):

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);
    }
};