我正在使用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
,即使鼠标位置发生变化,它也总是相同的内容。
我做错了什么?
答案 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);
}
}
....
}