Всплывающее меню 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);
то работает щелчок правой кнопкой мыши (но всплывающее меню не отображается).
Итак, как вы думаете, лучший способ заставить эти две функции (оба) работать?
Спасибо и извините за мой английский.
Ответы
Ответ 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);
}
};