2012-06-21 15 views
10

"¿Hay alguna manera de evitar que una JList seleccione el último elemento cuando el usuario hace clic debajo de él en la lista?"¿Cómo evitar que JList haga una selección fuera de los límites de la celda?

Esa es la pregunta que alguien hizo here y tengo el mismo problema. Ese tipo encontró una solución regular (anulando processMouseEvent()) pero quiero saber si hay una forma mejor/más elegante para hacerlo.

[Editar]

Ok, más detalles. Si tiene una JList y hay algún espacio desocupado por cualquier celda/elemento y hace clic en ese espacio, se seleccionó el último elemento de la Lista J.

Para un ejemplo real intente esto JList Swing Tutorial example, haga clic en el espacio en blanco y vea que Rollo fue seleccionado.

+0

SO ISN' generador de código t, para una mejor ayuda antes publicar un [SSCCE] (http://sscce.org/), de lo contrario mi respuesta es amplia ya que su pregunta es simple de 'consumir' – mKorbel

+0

@GuillaumePolet thnx, omite por completo ese aspecto – Alex

+0

@mKorbel simple ejemplo agregado – Alex

Respuesta

16

Descubre https://forums.oracle.com/forums/thread.jspa?threadID=2206996

import java.awt.EventQueue; 
import java.awt.Point; 
import java.awt.Toolkit; 
import java.awt.event.InputEvent; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 

import javax.swing.JFrame; 
import javax.swing.JList; 
import javax.swing.JScrollPane; 

public class TestJList { 
    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      public void run() { 
       JList list = new JList(new Object[] { "One", "Two", "Three" }) { 
        @Override 
        public int locationToIndex(Point location) { 
         int index = super.locationToIndex(location); 
         if (index != -1 && !getCellBounds(index, index).contains(location)) { 
          return -1; 
         } 
         else { 
          return index; 
         } 
        } 
       }; 

       list.addMouseListener(new MouseAdapter() { 

        @Override 
        public void mouseClicked(MouseEvent e) { 
         JList list = (JList) e.getSource(); 
         if (list.locationToIndex(e.getPoint()) == -1 && !e.isShiftDown() 
           && !isMenuShortcutKeyDown(e)) { 
          list.clearSelection(); 
         } 
        } 

        private boolean isMenuShortcutKeyDown(InputEvent event) { 
         return (event.getModifiers() & Toolkit.getDefaultToolkit() 
           .getMenuShortcutKeyMask()) != 0; 
        } 
       }); 

       JFrame frame = new JFrame("Test"); 
       frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
       frame.getContentPane().add(new JScrollPane(list)); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 
} 
+0

+1 excelente código, por ambos carteles en OTN, por favor, donde está la lista de todos los integrados 'putClientProperty (...)' en las API de Swing – mKorbel

+1

Considere también leyendo el comentario de Kleopatra debajo de la respuesta. Puede ser un poco incómodo borrar la selección. Mi expectativa hubiera sido que no pasa nada. Si he hecho una selección válida previamente (y no necesariamente la última celda) y luego hago clic fuera de la JList, me gustaría que la selección permanezca, no se borre –

2

En cuanto a la pila de llamadas, realmente no se puede hacer lo que quiera sin jugar con AWT-Events:

Thread [AWT-EventQueue-0] (Suspended (breakpoint at line 384 in DefaultListSelectionModel)) 
    DefaultListSelectionModel.changeSelection(int, int, int, int, boolean) line: 384  
    DefaultListSelectionModel.changeSelection(int, int, int, int) line: 415 
    DefaultListSelectionModel.setSelectionInterval(int, int) line: 459 
    TestJList$1(JList<E>).setSelectionInterval(int, int) line: 2067 
    BasicListUI$Handler.adjustSelection(MouseEvent) line: 2739 
    BasicListUI$Handler.mousePressed(MouseEvent) line: 2695 
    AWTEventMulticaster.mousePressed(MouseEvent) line: 280 
    TestJList$1(Component).processMouseEvent(MouseEvent) line: 6502 
    TestJList$1(JComponent).processMouseEvent(MouseEvent) line: 3321  
    TestJList$1.processMouseEvent(MouseEvent) line: 24 
    TestJList$1(Component).processEvent(AWTEvent) line: 6270  
    TestJList$1(Container).processEvent(AWTEvent) line: 2229  
    TestJList$1(Component).dispatchEventImpl(AWTEvent) line: 4861 
    TestJList$1(Container).dispatchEventImpl(AWTEvent) line: 2287 
    TestJList$1(Component).dispatchEvent(AWTEvent) line: 4687 
    LightweightDispatcher.retargetMouseEvent(Component, int, MouseEvent) line: 4832 
    LightweightDispatcher.processMouseEvent(MouseEvent) line: 4489 
    LightweightDispatcher.dispatchEvent(AWTEvent) line: 4422  
    JFrame(Container).dispatchEventImpl(AWTEvent) line: 2273  
    JFrame(Window).dispatchEventImpl(AWTEvent) line: 2713 
    JFrame(Component).dispatchEvent(AWTEvent) line: 4687  
    EventQueue.dispatchEventImpl(AWTEvent, Object) line: 707  
    EventQueue.access$000(EventQueue, AWTEvent, Object) line: 101 
    EventQueue$3.run() line: 666  
    EventQueue$3.run() line: 664  
    AccessController.doPrivileged(PrivilegedAction<T>, AccessControlContext) line: not available [native method]  
    ProtectionDomain$1.doIntersectionPrivilege(PrivilegedAction<T>, AccessControlContext, AccessControlContext) line: 76  
    ProtectionDomain$1.doIntersectionPrivilege(PrivilegedAction<T>, AccessControlContext) line: 87 
    EventQueue$4.run() line: 680  
    EventQueue$4.run() line: 678  

Se podría implementar su propio ListUI y luego haz lo que quieras (incluso prevenir este comportamiento no deseado), pero realmente no recomendaría ir por ese camino.

Por lo que vale la pena (que se realiza reemplazando métodos processXXXEvent), aquí es un pequeño fragmento que en realidad parece no tan feo y que impide seleccionar objetos al hacer clic fuera de sus límites:

import java.awt.event.MouseEvent; 

import javax.swing.JFrame; 
import javax.swing.JList; 
import javax.swing.JScrollPane; 
import javax.swing.SwingUtilities; 

public class TestJList { 

    private JList list; 

    protected void initUI() { 
     JFrame frame = new JFrame("test"); 
     list = new JList(new Object[] { "Hello", "World", "!" }) { 

      private boolean processEvent(MouseEvent e) { 
       int index = list.locationToIndex(e.getPoint()); 
       return index > -1 && list.getCellBounds(index, index).contains(e.getPoint()); 
      } 

      @Override 
      protected void processMouseEvent(MouseEvent e) { 
       if (processEvent(e)) { 
        super.processMouseEvent(e); 
       } 
      } 

      @Override 
      protected void processMouseMotionEvent(MouseEvent e) { 
       if (processEvent(e)) { 
        super.processMouseMotionEvent(e); 
       } 
      } 
     }; 
     list.setVisibleRowCount(10); 

     frame.add(new JScrollPane(list)); 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       new TestJList().initUI(); 
      } 
     }); 
    } 
} 
Cuestiones relacionadas