![](/img/trans.png)
[英]ListSelectionEvent, firing an event when clicking the currently selected item in JList
[英]JList - deselect when clicking an already selected item
如果單擊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);
......那很有效。 但我不喜歡它。 有沒有更好的辦法?
在此處查看示例“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;
}
}
});
這個怎么樣?
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);
}
}
它有效,但注意一個副作用...例如,如果你將模式設置為多重選擇,例如:
list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION );
您無法通過鼠標拖動選擇多個對象。 Ctrl(或shift)單擊工作。 我確定它可以修復,但我假設你問這個單選列表...如果不修改你的問題,我們就可以開始考慮多選問題的解決方案了。
我知道這個問題已經有了一個可接受的答案,但我認為我會擴展一點,因為我最終堅持這個任務幾個小時。
我試圖對所選項目實施點擊取消選擇操作,但我的列表實現需要使用單選模式,由
JList jlist = new JList(new DefaultListModel());
jlist.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
不幸的是,這導致許多SO問題上的點擊取消選擇問題的許多解決方案的異常和冗余調用,包括上面的FuryComptuers的 這個答案 。 由於DefaultListSelectionModel.class
代碼,特別是在addSelectionInterval(int index0, int index1)
和removeSelectionInterval(int index0, int index1)
方法中,這些方法調用回setSelectionInterval(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的回答解決了這個問題,但是當在所選項目上拖動鼠標時仍然會很奇怪(所選項目將在拖動鼠標時反復選擇和取消選擇)。 這似乎不是一個問題,但(顯然)我有一個顫抖的手,點擊時輕微的鼠標移動導致不必要的行為。 我結合了Sawas Dalkitsis的 回答和FuryComptuers的回答來獲得以下代碼,這似乎符合要求:
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);
注意:我沒有像Sawas Dalkitsis那樣針對ListSelectionModel.SINGLE_INTERVAL_SELECTION
檢查,因此如果在這種情況下實現它,請謹慎使用。
我擴展了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;
}
}
}
您可以始終使用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
在上面的java文件鏈接中有一個實現,可以很容易地改進來做“取消選擇”:)
當按下Shift鍵的同時使用鼠標點擊一次選擇多個項目時, Nick Dandoulakis的回答對我來說並不適用。
以下ListSelectionModel
在使用帶有Shift或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();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.