如何检测鼠标(指针)何时在JList中的文本?

时间:2014-10-12 06:25:58

标签: java swing popup row jlist

我正在使用JList来显示元素。我想提供一个弹出菜单来与鼠标下的特定元素进行交互。我正在使用MouseInputListener,isPopupTrigger(),locationToIndex(),getCellBounds()等。我没有为此发布代码,因为它不是重点,只是问题的背景。我最终想要做的只是在正确(平台和UI依赖)操作发生对JList单元格中的文本时发布弹出菜单 - 而不仅仅是行中的任何位置。我的JList位于SplitPane中的ScrollPane中。 JList单元格的宽度可以比文本大得多。如果用户能够在SplitPane远大于文本范围的情况下通过单击行中文本的右侧来发布弹出窗口,则将不清楚正在操作哪一行。我不想使用弹出菜单选择用户将要与之交互的行,因为选择在此上下文中具有不同的含义。所以基本的问题是:如何确定弹出触发器发生时的鼠标位置是否实际上在行中的文本上,而不是仅仅在行中?

1 个答案:

答案 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);
    }