2010-03-27 90 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(); 
     } 
    } 
相關問題