簡體   English   中英

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

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

在上面的java文件鏈接中有一個實現,可以很容易地改進來做“取消選擇”:)

當按下Shift鍵的同時使用鼠標點擊一次選擇多個項目時, Nick Dandoulakis的回答對我來說並不適用。

以下ListSelectionModel在使用帶有ShiftCtrl的鼠標點擊選擇項目時的行為與我期望的一樣。

此外,按住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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM