如何防止 JList 在单元格边界之外进行选择?
Posted
技术标签:
【中文标题】如何防止 JList 在单元格边界之外进行选择?【英文标题】:How to prevent JList from making selection outside cell bounds? 【发布时间】:2012-06-23 17:13:19 【问题描述】:“当用户点击列表中的最后一个元素时,有什么方法可以防止 JList 选择最后一个元素?”
这是有人问here 的问题,我也有同样的问题。那家伙找到了一个马马虎虎的解决方案(通过覆盖 processMouseEvent() ),但我想知道是否有更好/更优雅的方法来做到这一点。
[编辑]
好的,详细一点。 如果您有一个 JList 并且有一些空间未被任何单元格/元素占用,并且您单击该空间,则 JList 中的最后一个元素被选中。
举个真实的例子试试这个JList Swing Tutorial example,点击空白处,看看Rollo被选中了。
【问题讨论】:
SO 不是代码生成器,为了获得更好的帮助,请尽快发布SSCCE,否则我的答案很广泛,因为您的问题很简单consume
@GuillaumePolet thnx,完全忽略了这方面
@mKorbel 添加了简单示例
【参考方案1】:
见https://forums.oracle.com/forums/thread.jspa?threadID=2206996
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.InputEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
public class TestJList
public static void main(String[] args)
EventQueue.invokeLater(new Runnable()
public void run()
JList list = new JList(new Object[] "One", "Two", "Three" )
@Override
public int locationToIndex(Point location)
int index = super.locationToIndex(location);
if (index != -1 && !getCellBounds(index, index).contains(location))
return -1;
else
return index;
;
list.addMouseListener(new MouseAdapter()
@Override
public void mouseClicked(MouseEvent e)
JList list = (JList) e.getSource();
if (list.locationToIndex(e.getPoint()) == -1 && !e.isShiftDown()
&& !isMenuShortcutKeyDown(e))
list.clearSelection();
private boolean isMenuShortcutKeyDown(InputEvent event)
return (event.getModifiers() & Toolkit.getDefaultToolkit()
.getMenuShortcutKeyMask()) != 0;
);
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(new JScrollPane(list));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
);
【讨论】:
+1 优秀代码,由 OTN 上的两位发帖者提供,请查看 Swing API 中所有内置putClientProperty(...)
的列表
考虑在答案下方阅读 Kleopatra 的评论。清除选择可能有点不方便。我的期望是什么都不会发生。如果我之前做了一个有效的选择(不一定是最后一个单元格),然后我在 JList 外部单击,我希望选择保留,而不是被清除【参考方案2】:
查看调用堆栈,如果不弄乱 AWT-Events,您将无法真正做自己想做的事:
Thread [AWT-EventQueue-0] (Suspended (breakpoint at line 384 in DefaultListSelectionModel))
DefaultListSelectionModel.changeSelection(int, int, int, int, boolean) line: 384
DefaultListSelectionModel.changeSelection(int, int, int, int) line: 415
DefaultListSelectionModel.setSelectionInterval(int, int) line: 459
TestJList$1(JList<E>).setSelectionInterval(int, int) line: 2067
BasicListUI$Handler.adjustSelection(MouseEvent) line: 2739
BasicListUI$Handler.mousePressed(MouseEvent) line: 2695
AWTEventMulticaster.mousePressed(MouseEvent) line: 280
TestJList$1(Component).processMouseEvent(MouseEvent) line: 6502
TestJList$1(JComponent).processMouseEvent(MouseEvent) line: 3321
TestJList$1.processMouseEvent(MouseEvent) line: 24
TestJList$1(Component).processEvent(AWTEvent) line: 6270
TestJList$1(Container).processEvent(AWTEvent) line: 2229
TestJList$1(Component).dispatchEventImpl(AWTEvent) line: 4861
TestJList$1(Container).dispatchEventImpl(AWTEvent) line: 2287
TestJList$1(Component).dispatchEvent(AWTEvent) line: 4687
LightweightDispatcher.retargetMouseEvent(Component, int, MouseEvent) line: 4832
LightweightDispatcher.processMouseEvent(MouseEvent) line: 4489
LightweightDispatcher.dispatchEvent(AWTEvent) line: 4422
JFrame(Container).dispatchEventImpl(AWTEvent) line: 2273
JFrame(Window).dispatchEventImpl(AWTEvent) line: 2713
JFrame(Component).dispatchEvent(AWTEvent) line: 4687
EventQueue.dispatchEventImpl(AWTEvent, Object) line: 707
EventQueue.access$000(EventQueue, AWTEvent, Object) line: 101
EventQueue$3.run() line: 666
EventQueue$3.run() line: 664
AccessController.doPrivileged(PrivilegedAction<T>, AccessControlContext) line: not available [native method]
ProtectionDomain$1.doIntersectionPrivilege(PrivilegedAction<T>, AccessControlContext, AccessControlContext) line: 76
ProtectionDomain$1.doIntersectionPrivilege(PrivilegedAction<T>, AccessControlContext) line: 87
EventQueue$4.run() line: 680
EventQueue$4.run() line: 678
您可以实现自己的 ListUI,然后做任何您想做的事情(包括防止这种不需要的行为),但我真的不建议您走这条路。
对于它的价值(它是通过覆盖 processXXXEvent 方法完成的),这里有一个小 sn-p,我实际上发现它并不难看,并且可以防止在超出范围点击时选择对象:
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class TestJList
private JList list;
protected void initUI()
JFrame frame = new JFrame("test");
list = new JList(new Object[] "Hello", "World", "!" )
private boolean processEvent(MouseEvent e)
int index = list.locationToIndex(e.getPoint());
return index > -1 && list.getCellBounds(index, index).contains(e.getPoint());
@Override
protected void processMouseEvent(MouseEvent e)
if (processEvent(e))
super.processMouseEvent(e);
@Override
protected void processMouseMotionEvent(MouseEvent e)
if (processEvent(e))
super.processMouseMotionEvent(e);
;
list.setVisibleRowCount(10);
frame.add(new JScrollPane(list));
frame.pack();
frame.setVisible(true);
public static void main(String[] args)
SwingUtilities.invokeLater(new Runnable()
@Override
public void run()
new TestJList().initUI();
);
【讨论】:
以上是关于如何防止 JList 在单元格边界之外进行选择?的主要内容,如果未能解决你的问题,请参考以下文章
如何将 UICollectionViewCell 的可触摸区域扩展到其边界之外?
将 UIImageView 添加到单元格边界之外的 UITableViewCell
iOS:如何让 UITableView 将其单元格绘制出边界?