我正在使用JList来显示元素。我想提供一个弹出菜单来与鼠标下的特定元素进行交互。我正在使用MouseInputListener,isPopupTrigger(),locationToIndex(),getCellBounds()等。我没有为此发布代码,因为它不是重点,只是问题的背景。我最终想要做的只是在正确(平台和UI依赖)操作发生对JList单元格中的文本时发布弹出菜单 - 而不仅仅是行中的任何位置。我的JList位于SplitPane中的ScrollPane中。 JList单元格的宽度可以比文本大得多。如果用户能够在SplitPane远大于文本范围的情况下通过单击行中文本的右侧来发布弹出窗口,则将不清楚正在操作哪一行。我不想使用弹出菜单选择用户将要与之交互的行,因为选择在此上下文中具有不同的含义。所以基本的问题是:如何确定弹出触发器发生时的鼠标位置是否实际上在行中的文本上,而不是仅仅在行中?
答案 0 :(得分:2)
如果JList的单元格渲染器返回JLabel(默认情况下,或者如果您将渲染器设置为DefaultListCellRenderer),则可以使用SwingUtilities.layoutCompoundLabel来确定文本的边界:< / p>
static <E> boolean isOverText(Point location,
JList<E> list) {
int index = list.locationToIndex(location);
if (index < 0) {
return false;
}
E value = list.getModel().getElementAt(index);
ListCellRenderer<? super E> renderer = list.getCellRenderer();
Component c = renderer.getListCellRendererComponent(list, value, index,
list.isSelectedIndex(index),
list.getSelectionModel().getLeadSelectionIndex() == index);
if (c instanceof JLabel) {
JLabel label = (JLabel) c;
Icon icon = null;
if (!label.isEnabled()) {
icon = label.getDisabledIcon();
}
if (icon == null) {
icon = label.getIcon();
}
Rectangle listItemBounds =
SwingUtilities.calculateInnerArea(label, null);
Rectangle cellBounds = list.getCellBounds(index, index);
listItemBounds.translate(cellBounds.x, cellBounds.y);
listItemBounds.width = cellBounds.width;
listItemBounds.height = cellBounds.height;
Rectangle textBounds = new Rectangle();
Rectangle iconBounds = new Rectangle();
SwingUtilities.layoutCompoundLabel(label,
label.getFontMetrics(label.getFont()),
label.getText(),
icon,
label.getVerticalAlignment(),
label.getHorizontalAlignment(),
label.getVerticalTextPosition(),
label.getHorizontalTextPosition(),
listItemBounds,
iconBounds,
textBounds,
label.getIconTextGap());
return textBounds.contains(location);
}