2011-05-15 24 views
21

aquí está mi problema: Tengo una jList y un menú emergente. Cuando hago clic derecho en jList, aparece el menú emergente. El problema es que el elemento jList al que apunta el mouse no seleccionará. Y quiero que haga eso. Cuando señalo el cursor en un elemento de la lista y presiono el botón derecho, quiero que ocurran dos cosas. Seleccione el elemento en el que hice clic y muestre el menú emergente.menú desplegable Java swing y jlist

yo probamos este:

jLists.addMouseListener(new MouseAdapter() { 

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

jList.setComponentPopupMenu(jPopupMenu); 

Pero sólo se muestra el menú emergente. Si elimino esta línea:

jList.setComponentPopupMenu(jPopupMenu); 

entonces el haga clic con obras selectas (pero el menú emergente no se muestra).

Entonces, ¿cuál cree que es la mejor manera de hacer que estas dos funciones (ambas) funcionen?

Gracias y lo siento por mi inglés.

Respuesta

27

No haga setComponentPopupMenu. En el MouseAdapter haga lo siguiente:

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

Esto debería funcionar.

EDIT: El código ahora comprueba ambos press y release eventos, debido a que algunas plataformas muestran ventanas emergentes cuando se presione el ratón y algunos otros en la liberación. Ver the Swing tutorial para más información.

+0

un gran fan de código no probado, pero se vio obligado a dar un voto para el control de hasta 'isPopupTrigger()' - buena llamada. –

+0

Sí, funciona.Gracias ! – VaclavDedik

+0

@Vena, @Andrew Thompson: De nada. –

9

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
+1

la parte que falta es 'JList = new JList () {@ Override Punto getPopupLocation (MouseEvent evento) { JListUtility.getPopupLocation retorno pública (esto, evento); } }; ' – palindrom

+0

Gracias, @palindrom. Actualicé mi respuesta para incluir el uso de 'getPopupLocation' –

Cuestiones relacionadas