Si desea continuar utilizando setComponentPopupMenu
(lo cual es bueno porque maneja las invocaciones de mouse y teclado de la ventana emergente de forma cruzada), puede anular JPopupMenu.show(Component, int, int)
para seleccionar la fila adecuada.
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);
Tenga en cuenta que cuando el emergente se invoca a través del teclado (y que no anula también getPopupLocation
en su componente de destino), la posición x, y que se obtiene en JPopupMenu.show
será el punto medio de su componente. Si ya hay una selección en este caso, probablemente no desee cambiar la selección.
La solución que se me ocurrió para resolver el problema de invocación de teclado frente a ratón fue establecer una propiedad de cliente en el componente en una modificación de getPopupLocation
y luego comprobarlo cuando se muestra la ventana emergente. El argumento a getPopupLocation
será null
cuando se invoca a través del teclado. Aquí está el código central (tal vez implementado en una clase de utilidad disponible para su componente y su menú emergente).
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));
}
Entonces anular getPopupLocation
en su componente:
@Override
public Point getPopupLocation(MouseEvent event)
{
return PopupMenuUtils.getPopupLocation(this, event);
}
y llame isPopupTriggeredByMouseEvent
en una anulación de los JPopupMenu.show
para determinar si o no para seleccionar la fila en la posición emergente (o cualquier acción que puede tener sentido para el componente subyacente):
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);
}
};
No
un gran fan de código no probado, pero se vio obligado a dar un voto para el control de hasta 'isPopupTrigger()' - buena llamada. –
Sí, funciona.Gracias ! – VaclavDedik
@Vena, @Andrew Thompson: De nada. –