繁体   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