对于我所处的情况,我有点困惑。我创建了一个ListModel,扩展了DefaultListModel和ListRenderer,实现了ListCellRenderer,用于在JList中显示自定义单元格。这些单元格是从扩展JPanel的类创建的一些对象,它们包含JLabel和JButton。JList对象中的MouseEvents
我的问题是关于鼠标事件:我想触发某个事件,当点击JList的单元格内的JButton,但我不知道如何匹配鼠标源点和JButton从各自的指数。更确切地说,我在列表中添加了一个鼠标监听器,但是我希望它在鼠标点位于JButton的边界内时触发某些事件,并且如果它位于数据项上,则会触发其他操作。我加了一些打印,找出这个原因,但在此之前,一些代码来突出结构:
public WifiGuiHandler(JButton reference) {
btnReference = reference;
wifiListener = new WifiListener();
wifiPopupContainer = new JScrollPopupMenu("Connections.");
wifiPopupContainer.setMaximumVisibleRows(7);
connectionsHolder = new ArrayList<>();
listOfConnections = new JList();
listOfConnectionsModel = new ListModel(connectionsHolder);
listOfConnectionsRenderer = new ListRenderer();
listOfConnections.setModel(listOfConnectionsModel);
listOfConnections.setCellRenderer(listOfConnectionsRenderer);
wifiPopupContainer.add(listOfConnections);
wifiPopupContainer.pack();
initializeTestVariables();
initializeListeners();
}
这里,构造函数接受一个JButton,并增加了一个鼠标侦听器,它的类,即触发一个JPopupMenu(仅包含一个组件)的外观,该JList包含整个数据。此外,将ArrayList与数据项链接到ListModel。
public void initializeTestVariables() {
for (int i = 0; i <= 10; i++) {
WifiItem item = new WifiItem("Connection number " + i + ".", i);
connectionsHolder.add(item);
}
}
设置数据项目。
public void initializeListeners() {
listOfConnections.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
int index = listOfConnections.locationToIndex(e.getPoint());
if (index >= 0) {
WifiItem item = (WifiItem) ((ListModel) listOfConnections.getModel()).getElementAt(index);
System.out.println("Button of " + item.getConnectionName() + " is at location :" + item.getButton().getLocation());
System.out.println("Button has the bounds : " + item.getButton().getBounds());
System.out.println("MouseEvent detected on : " + e.getPoint().getLocation());
if (item.getButton().getBounds().contains(e.getPoint())) {
item.connectHere();
}
if (item.getButton().isVisible()) {
System.out.println("Set expanded on : " + item.getConnectionName());
item.setExpandedState(false);
listOfConnectionsModel.fireContentsChanged(item, index, index);
updateGui(false);
} else {
System.out.println("Set expanded on : " + item.getConnectionName());
listOfConnectionsModel.fireContentsChanged(item, index, index);
item.setExpandedState(true);
updateGui(false);
}
}
}
});
btnReference.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
updateGui(true);
}
});
}
而这正是混乱发生的地方。我正确地从鼠标事件位置/点获取数据项(WifiItem),但是当我点击WifiItem的JButton时,它不触发该方法,就像它似乎没有检测到JButton实际上在那里。我还设置了印刷品,奇怪的是,JButton的Point始终是相同的,即使它实际上是不同的,这似乎是问题所在。更确切地说,从该程序的输出:
的连接号码2.按钮在位置:java.awt.Point中[X = 137,Y = 33]
按钮具有界限:JAVA .awt.Rectangle [X = 137,Y = 33,宽度= 90,高度= 26]
的MouseEvent检测到:连接的java.awt.Point中[X = 172,Y = 125]
按钮number is 3. is at location:java.awt.Point [x = 137,y = 33]
Button has t他界定:java.awt.Rectangle中[X = 137,Y = 33,宽度= 90,高度= 26]
的MouseEvent检测到:java.awt.Point中[X = 172,Y = 125]
上面的鼠标事件点实际上位于JButton本身,只是它没有得到。另一个奇怪的事实是,只有当我点击列表的FIRST元素的JButton时,才会触发所需的鼠标操作。
另一份印刷文件显示,所有的JButton都有相同的Point和Rectangle,我不明白。 JList中有10个项目,每个项目都显示正确,他们所有的JButton具有相同的位置?我必须在这里错过一些关键因素。我查看了其他帖子并尝试了其他建议:使用SwingUtilities转换该点,从JList中移除所有鼠标侦听器并将它们添加到数据项。总结一下,问题是列表触发了正确数据项的事件(也就是说,我确实在那里找到正确的索引),但是如果鼠标事件发生在JButton上的任何数据项列表中,它不会触发所需的效果(即使它应该是,该点不在按钮的范围内)。
明天我会尝试切换到JTable,我首先考虑使用它,但我不希望我的数据在列中分开,因为在我的数据项类(WifiItem)中,该按钮在标签下方对齐显示文字,用于设计目的(由团队成员建议)。此外,如代码中所示,当您点击这些项目时,它将“最小化”(隐藏按钮并调整大小,使其仅显示标签)或“最大化”(显示按钮并扩大其大小)。感谢您的建议,无论如何,我会明天尝试,并带来结果。 – g0dzax
@ g0dzax,'该按钮在显示文本的标签下方对齐,' - JTable不适用于此。请参阅编辑以获取其他评论 – camickr
将高度添加到计算中的想法非常出色。我会尝试。 – g0dzax