2010-03-27 33 views
9

Si se hace clic en un índice seleccionado en una JList, quiero que se anule la selección. En otras palabras, al hacer clic en los índices en realidad se alterna su selección. No parece que este fue apoyada, por lo que tratéJList - anule la selección al hacer clic en un elemento ya seleccionado

list.addMouseListener(new MouseAdapter() 
{ 
    public void mousePressed(MouseEvent evt) 
    { 
     java.awt.Point point = evt.getPoint(); 
     int index = list.locationToIndex(point); 
     if (list.isSelectedIndex(index)) 
     list.removeSelectionInterval(index, index); 
    } 
}); 

El problema aquí es que esto se invoca después de JList ya ha actuado en el caso del ratón, por lo que anula la selección de todo. Entonces intenté eliminar todos los MouseListeners de JList, agregué los míos y luego volví a agregar todos los oyentes predeterminados. Eso no funcionó, ya que JList volvería a seleccionar el índice después de que lo deseleccionara. De todos modos, lo que eventualmente se me ocurrió es

MouseListener[] mls = list.getMouseListeners(); 
for (MouseListener ml : mls) 
    list.removeMouseListener(ml); 
list.addMouseListener(new MouseAdapter() 
{ 
    public void mousePressed(MouseEvent evt) 
    { 
     java.awt.Point point = evt.getPoint(); 
     final int index = list.locationToIndex(point); 
     if (list.isSelectedIndex(index)) 
     SwingUtilities.invokeLater(new Runnable() 
     { 
      public void run() 
      { 
       list.removeSelectionInterval(index, index); 
      } 
     }); 
    } 
}); 
for (MouseListener ml : mls) 
    list.addMouseListener(ml); 

... y eso funciona. Pero no me gusta ¿Hay una mejor manera?

+0

Honestamente, lo habría hecho como usted ya lo describe, usando un 'MouseAdapter'. Si hay una solución más elegante, me encantaría saber sobre eso también. –

+0

Esto es compatible por defecto en JList, pero tiene que presionar Ctrl-Click (al menos en Windows) en un elemento seleccionado para anular su selección. – lbalazscs

Respuesta

0

Puede siempre ListSelectionListener en lugar de descifrar el punto en el que se hizo clic y luego traducirlo al elemento seleccionado.

http://java.sun.com/docs/books/tutorial/uiswing/examples/events/index.html#ListSelectionDemo

http://java.sun.com/docs/books/tutorial/uiswing/events/listselectionlistener.html

http://java.sun.com/docs/books/tutorial/uiswing/examples/events/ListSelectionDemoProject/src/events/ListSelectionDemo.java

en el siguiente enlace para el archivo de Java no es una aplicación que se puede mejorar fácilmente hacer "anulación de la selección" :)

+0

Si en un elemento ya seleccionado se hace clic en 'ListSelectionListener.valueChanged' no se llamará, ya que la selección no se cambia. Por lo tanto, no puede anular la selección del elemento ya seleccionado dentro de este método. – ablaeul

4

¿Qué tal esto?

import javax.swing.DefaultListSelectionModel; 
import javax.swing.JFrame; 
import javax.swing.JList; 
import javax.swing.ListSelectionModel; 

public class A { 
    public static void main(String[] args) { 
     JFrame f = new JFrame("Test"); 
     final JList list = new JList(new String[] {"one","two","three","four"}); 
     list.setSelectionModel(new DefaultListSelectionModel(){ 


      @Override 
      public void setSelectionInterval(int index0, int index1) { 
       if (index0==index1) { 
        if (isSelectedIndex(index0)) { 
         removeSelectionInterval(index0, index0); 
         return; 
        } 
       } 
       super.setSelectionInterval(index0, index1); 
      } 

      @Override 
      public void addSelectionInterval(int index0, int index1) { 
       if (index0==index1) { 
        if (isSelectedIndex(index0)) { 
         removeSelectionInterval(index0, index0); 
         return; 
        } 
       super.addSelectionInterval(index0, index1); 
       } 
      } 

     }); 
     f.getContentPane().add(list); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.pack(); 
     f.setVisible(true); 
    } 

} 

funciona, pero tenga en cuenta un efecto secundario ... Si se ajusta el modo de múltiples disegno como este por ejemplo:

list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); 

no puede seleccionar varios objetos a través de arrastrar el ratón. Ctrl (o shift) haga clic en funciona. Estoy seguro de que se puede arreglar, pero supongo que usted pidió esto para listas de selección individuales ... Si no, modifique su pregunta y podemos comenzar a pensar en soluciones para el problema de la selección múltiple.

10

Mirando el ejemplo "ListSelectionModel: Activación del modo de selección de palanca" aquí: http://java.sun.com/products/jfc/tsc/tech_topics/jlist_1/jlist.html

lo he modificado ligeramente para selección múltiple cuadros de lista (cambio setSelectionInterval a addSelectionInterval) y se elimina un problema con la re-selección si hace clic para anular la selección y mueve el mouse mientras el mouse está hacia abajo (movió la marca gestual Comenzó para agregar y eliminar).

objList.setSelectionModel(new DefaultListSelectionModel() { 
    private static final long serialVersionUID = 1L; 

    boolean gestureStarted = false; 

    @Override 
    public void setSelectionInterval(int index0, int index1) { 
     if(!gestureStarted){ 
      if (isSelectedIndex(index0)) { 
       super.removeSelectionInterval(index0, index1); 
      } else { 
       super.addSelectionInterval(index0, index1); 
      } 
     } 
     gestureStarted = true; 
    } 

    @Override 
    public void setValueIsAdjusting(boolean isAdjusting) { 
     if (isAdjusting == false) { 
      gestureStarted = false; 
     } 
    } 

}); 
+0

Funciona como un encanto, gracias. – brimborium

2

Sé que esta pregunta ya tiene una respuesta aceptada, pero pensé que me gustaría ampliar un poco, ya que terminó atascado en esta tarea durante unas horas.

yo estaba tratando de implementar una acción de clic para anular la selección de los elementos seleccionados, pero mi implementación de la lista requiere el uso de modo de un solo Selección, especificado por

JList jlist = new JList(new DefaultListModel()); 
jlist.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 

Desafortunadamente, esto dio lugar a excepciones y redundante requiere muchas de las soluciones para el problema de hacer clic para deseleccionar en muchas preguntas de SO, incluido this answer por FuryComptuers anterior.Debido al código en DefaultListSelectionModel.class, específicamente en los métodos addSelectionInterval(int index0, int index1) y removeSelectionInterval(int index0, int index1), que devuelve las llamadas al método setSelectionInterval(int index0, int index1), se produce una llamada circular que conduce a excepciones (obviamente). Este código de "problema" se puede ver a continuación.

// If we only allow a single selection, channel through 
    // setSelectionInterval() to enforce the rule. 
    if (getSelectionMode() == SINGLE_SELECTION) { 
     setSelectionInterval(index0, index1); 
     return; 
    } 

Sawas Dalkitsis 'answer resolvieron este problema, pero aún así actuar raro cuando arrastrando el ratón sobre un elemento seleccionado (el elemento seleccionado seleccionará y anular la selección de una y otra vez mientras se arrastra el ratón). Esto no parece ser un problema, pero (aparentemente) tengo una mano temblorosa, y movimientos menores del mouse al hacer clic en el resultado en un comportamiento no deseado. Combiné Sawas Dalkitsisanswer y FuryComptuers 's answer para obtener el código siguiente, que parece funcionar como se desea:

JList jlist = new JList(new DefaultListModel()); 
    jList.setSelectionModel(new DefaultListSelectionModel() { 
     private static final long serialVersionUID = 1L; 

     boolean gestureStarted = false; 

     @Override 
     public void setSelectionInterval(int index0, int index1) { 
      if(!gestureStarted){ 
      if (index0==index1) { 
       if (isSelectedIndex(index0)) { 
        removeSelectionInterval(index0, index0); 
        return; 
       } 
      } 
      super.setSelectionInterval(index0, index1); 
      } 
      gestureStarted = true; 
     } 

     @Override 
     public void addSelectionInterval(int index0, int index1) { 
      if (index0==index1) { 
       if (isSelectedIndex(index0)) { 
        removeSelectionInterval(index0, index0); 
        return; 
       } 
      super.addSelectionInterval(index0, index1); 
      } 
     } 

     @Override 
     public void setValueIsAdjusting(boolean isAdjusting) { 
      if (isAdjusting == false) { 
       gestureStarted = false; 
      } 
     } 

    }); 
    jList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 

Nota: No vi esto en contra de la ListSelectionModel.SINGLE_INTERVAL_SELECTION, como Sawas Dalkitsis lo hicieron, así que tenga cuidado si la implementación en ese caso.

0

Extendí FuryComptuers respondí que admitía la selección múltiple y solucioné un problema donde setSelectionInterval no funcionaba si se llamaba directamente.

public class ToggleableListSelectionModel extends DefaultListSelectionModel { 
    private static final long serialVersionUID = 1L; 

    private boolean mGestureStarted; 

    @Override 
    public void setSelectionInterval(int index0, int index1) { 
     // Toggle only one element while the user is dragging the mouse 
     if (!mGestureStarted) { 
      if (isSelectedIndex(index0)) { 
       super.removeSelectionInterval(index0, index1); 
      } else { 
       if (getSelectionMode() == SINGLE_SELECTION) { 
        super.setSelectionInterval(index0, index1); 
       } else { 
        super.addSelectionInterval(index0, index1); 
       } 
      } 
     } 

     // Disable toggling till the adjusting is over, or keep it 
     // enabled in case setSelectionInterval was called directly. 
     mGestureStarted = getValueIsAdjusting(); 
    } 

    @Override 
    public void setValueIsAdjusting(boolean isAdjusting) { 
     super.setValueIsAdjusting(isAdjusting); 

     if (isAdjusting == false) { 
      // Enable toggling 
      mGestureStarted = false; 
     } 
    } 
} 
0

Nick Dandoulakis' answer hizo el trabajo no es para mí la hora de seleccionar varios elementos a la vez mediante un clic del ratón mientras presiona Shift .

Los siguientes ListSelectionModel se comporta como me lo cuenta al seleccionar elementos utilizando clics del mouse con Shift o Ctrl.

Además, al mantener pulsado Shift + Ctrl y presionando o selecciona los elementos de la manera que quiero que haga.

public static class ToggleableListSelectionModel extends DefaultListSelectionModel { 
     private static final long serialVersionUID = 1L; 

     @Override 
     public void setSelectionInterval(int startIndex, int endIndex) { 
      if (startIndex == endIndex) { 
       if (multipleItemsAreCurrentlySelected()) { 
        clearSelection(); 
       } 
       if (isSelectedIndex(startIndex)) { 
        clearSelection(); 
       } 
       else { 
        super.setSelectionInterval(startIndex, endIndex); 
       } 
      } 
      // User selected multiple items 
      else { 
       super.setSelectionInterval(startIndex, endIndex); 
      } 
     } 

     private boolean multipleItemsCurrentlyAreSelected() { 
      return getMinSelectionIndex() != getMaxSelectionIndex(); 
     } 
    } 
Cuestiones relacionadas