JList - locationToIndex()始终为线程中的鼠标位置返回相同的索引

时间:2014-03-29 02:33:58

标签: java multithreading swing jlist point

我正在使用JLists测试一下,我想在MouseEnter上弹出一个小窗口,显示鼠标悬停在列表条目的内容;也可以在MouseExit上配置窗口 到目前为止,这工作得很好,但是为了更新鼠标必须退出并重新进入。

现在我想让它在并行线程中工作并一直更新窗口,所以如果我不必先退出就会改变它,并尝试了这个:

     public void run() {
            while (!Thread.interrupted()) {
                Point p = MouseInfo.getPointerInfo().getLocation();
                String text = list.getModel().getElementAt(
                        list.locationToIndex(p));
                lab.setText(text);
            }

但它总是只显示列表中最后一个条目的内容,无论鼠标在哪里 如果我打印出text,即使鼠标位置发生变化,它也总是相同的内容。

我做错了什么?

3 个答案:

答案 0 :(得分:3)

MouseInfo.getPointerInfo().getLocation()给出了屏幕上下文中鼠标的位置。

JList#locationToIndex期望该点位于JList

的上下文中

起初这可能有点令人困惑,但基本上,在处理这样的功能时,组件除了要在其坐标上下文中的点之外,其中0x0是组件的左上角。这实际上使生活变得更加容易,因为您不需要经常在屏幕和组件坐标之间进行转换......

您需要先将Point转换为组件坐标...

SwingUtilities.convertPointFromScreen(p, list);

然后请求由点

表示的索引

另请注意,Swing不是线程安全的,这意味着您应该只从事件调度线程的上下文中访问或修改UI组件。

所以这就是......

String text = list.getModel().getElementAt(
                    list.locationToIndex(p));
lab.setText(text);

......非常危险。

有关详细信息,请参阅Concurrency in Swing

如果不确切知道您要做什么,很难提供替代建议,但您可以考虑使用JList和/或MouseListener注册MouseEvent,而不是

这样做的直接好处是{{1}}已经转换为触发事件的组件的坐标空间

答案 1 :(得分:0)

使用此代码代替您的代码

        Point p = MouseInfo.getPointerInfo().getLocation();
        list.setSelectedIndex(list.locationToIndex(p));

        String text = list.getSelectedValue().toString();
        lab.setText(text);

答案 2 :(得分:0)

private void JLISTE_clicked(java.awt.event.MouseEvent evt) {                                        
    if (SwingUtilities.isRightMouseButton(evt)){
        if (evt.getComponent()==JLISTE){
            int idx = JLISTE.locationToIndex(evt.getPoint());
            System.out.println("Index rightclicked : " + idx); // testing
            JLISTE.setSelectedIndex(idx);
        }
    }
....
}