【问题标题】:JList - locationToIndex() always returning the same index for mouse location in threadJList - locationToIndex() 总是为线程中的鼠标位置返回相同的索引
【发布时间】:2014-03-29 02:33:58
【问题描述】:

我正在使用 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它总是相同的内容,即使鼠标位置发生变化。

我做错了什么?

【问题讨论】:

    标签: java multithreading swing jlist point


    【解决方案1】:

    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

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

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

    【讨论】:

    • 另一个简单的问题,你有什么建议让我让窗口随着鼠标的位置动态改变它的位置,所以它不会停留在它第一次出现的位置?使用window.setLocation(p) 让它出现和消失的非常快而且不好看,有没有什么好的办法呢?
    • 老实说,最好的解决方案是setLocation 问题是,你想做什么
    • +1 使用 ListSelectionListener 而不是 MouseWhatever,但 HightLigter 可以这样工作,也许是在谈论渲染器的概念
    【解决方案2】:

    用这个代码代替你的代码

            Point p = MouseInfo.getPointerInfo().getLocation();
            list.setSelectedIndex(list.locationToIndex(p));
    
            String text = list.getSelectedValue().toString();
            lab.setText(text);
    

    【讨论】:

    • e 来自哪里?
    【解决方案3】:
    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);
            }
        }
    ....
    }
    

    【讨论】:

    • 欢迎来到 Stack Overflow!虽然这段代码 sn-p 可能是解决方案,但包含解释确实有助于提高帖子的质量。请记住,您是在为将来的读者回答问题,而这些人可能不知道您提出代码建议的原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-04
    • 2014-07-18
    • 2013-10-16
    • 2020-03-26
    • 1970-01-01
    • 2014-05-01
    相关资源
    最近更新 更多