Если вы хотите продолжить использовать 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);
}
};
Не большой поклонник непроверенного кода, но он был вынужден дать голосование за проверку 'isPopupTrigger()' - хорошего вызова. –
Да, это работает.Благодаря ! – VaclavDedik
@Vena, @Andrew Thompson: Добро пожаловать. –