2010-03-27 89 views
9

如果单击JList上的选定索引,我希望它取消选择。换句话说,点击索引实际上会切换其选择。不像这是支持的,所以我想JList - 单击已选择的项目时取消选择

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

这里的问题是,这是正在调用 JList中已经作用于鼠标事件,所以它会取消一切。于是我尝试删除所有JList的MouseListeners,添加我自己的,然后添加所有默认侦听器。这是行不通的,因为JList在取消选择之后会重新选择索引。无论如何,我最终想出的是

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); 

...和那个作品。但我不喜欢它。有没有更好的办法?

+0

老实说,我会按照你已经描述的,使用'MouseAdapter'完成它。如果有更优雅的解决方案,我也很乐意听到。 –

+0

默认情况下,JList支持此功能,但您必须对所选项目进行Ctrl-点击(至少在Windows上)才能取消选择它。 – lbalazscs

回答

0

您可以始终使用ListSelectionListener而不是解密点击的点,然后将其转换为选定的项目。

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

在上面的链接的Java文件也可以很容易地提高办 “取消选择” 实现:)

+0

如果在已经选择的元素上单击,将不会调用“ListSelectionListener.valueChanged”,因为选择不会更改。所以你不能在这个方法中取消已经选择的元素。 – ablaeul

4

这个怎么样?

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

} 

它的工作原理,但注意药物的副作用......如果将模式设置为多selction这样的,例如:

list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); 

不能选择通过鼠标拖动多个对象。 Ctrl(或shift)点击工程。我相信它可以被修复,但我想你问这个单选列表...如果不修改你的问题,我们可以开始考虑多选问题的解决方案。

10

望着示例“的ListSelectionModel:启用切换选择模式”的位置: http://java.sun.com/products/jfc/tsc/tech_topics/jlist_1/jlist.html

我稍微修改了它的多选列表框(改为setSelectionInterval到addSelectionInterval),并消除了重新选择,如果有问题在鼠标关闭时单击以取消选择并移动鼠标(将gestureStarted移动到添加和移除状态)。

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

作品像一个魅力,谢谢。 – brimborium

2

我知道这个问题已经有一个公认的答案,但我以为我会扩大一点,因为我最终卡在这个任务了几个小时。

我试图实现对选定项目点击到取消行动,但我的列表实现,需要使用单一选择模式,通过

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

不幸的是指定的,这导致了异常和冗余需要针对许多SO问题的许多解决方案来实现点击取消选择问题,其中包括this answer上面的FuryComptuers。由于DefaultListSelectionModel.class中的代码,特别是在调用setSelectionInterval(int index0, int index1)方法的addSelectionInterval(int index0, int index1)removeSelectionInterval(int index0, int index1)方法中导致了循环调用,导致(明显)异常。这个“问题”代码可以在下面看到。

// 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解决了这个问题,但所选项目拖动鼠标时(所选择的项目将选择和去选择自己一遍又一遍,同时拖动鼠标)将仍然采取行动怪异。这似乎不是一个问题,但(显然)我有一个不稳定的手,而点击时轻微的鼠标移动导致不需要的行为。我结合Sawas DalkitsisanswerFuryComptuersanswer得到下面的代码,这似乎为所需的工作:

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); 

注:我没有检查这对ListSelectionModel.SINGLE_INTERVAL_SELECTION,为Sawas Dalkitsis一样,所以要小心,如果实施在那种情况下。

0

我扩展了FuryComptuers答案以支持多选,并修复了如果直接调用setSelectionInterval不起作用的问题。

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一次使用鼠标点击的同时按下Shift键选择多个项目时,为我做的不太工作。

以下ListSelectionModel的行为与Ctrl键选择使用鼠标点击的项目时,我会想到它。

此外,按住SHIFT + CTRL和按任一选择的项目,我希望它的方式。

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(); 
     } 
    } 
相关问题