QListView.indexAt 在 PyQt5 中返回错误的索引?
QListView.indexAt in PyQt5 returning wrong index?
我试图在用户右键单击 QListView 中的项目时弹出上下文菜单,如果用户在任何项目之外(任何空白处)右键单击则弹出不同的上下文菜单.我发现我在执行 indexAt 命令时收到的索引不准确,我不知道为什么。
我将 QListView 初始化为它自己的 class:
class RBKDataTypesTab(QWidget):
def __init__(self):
super().__init__()
self.models = []
grid = QGridLayout()
self.list = QListView()
self.list.clicked.connect(self.list_item_selected)
grid.addWidget(self.list, 0, 0, -1, 8)
self.table = QTableView()
self.indexMenu = QMenu()
self.indexMenu.addAction('Add DataType', self.addDataType)
self.indexMenu.addAction('Remove DataType', self.removeDataType)
self.nonIndexMenu = QMenu()
self.nonIndexMenu.addAction('Add DataType', self.addDataType)
grid.addWidget(self.table, 0, 2, -1, -1)
self.setLayout(grid)
此时,列表为空。当打开文件以设置模型时,我还有其他功能,它将数据加载到屏幕上。
这是我的上下文菜单事件:
def contextMenuEvent(self, event):
index = self.list.indexAt(event.pos())
print(index.data())
if(index.isValid()):
event.accept()
self.indexMenu.exec_(event.globalPos())
else:
event.accept()
self.nonIndexMenu.exec_(event.globalPos())
假设我有三个通用项目:
- item1
- item2
- item3
感谢 print 语句,我可以知道当我单击 QListView 中 item1 的顶部 1/4 时,它正在返回 item1。但是,如果我单击 item1 的底部 3/4,它将返回 item2。 item2 和 item3 的逻辑相同,只有 item3 的底部 3/4 returns None,因此返回错误的上下文菜单。
谁能帮我理解为什么会这样?我认为它与 event.pos() 有关,但我不知道是什么。
谢谢!!
event.pos()
的坐标是相对于拥有 contextMenuEvent()
方法的小部件而言的,在您的情况下它是相对于 window 但 indexAt()
方法需要相对于视图 (QListView) 的 viewport()
的坐标,因此您必须使用 mapFromGlobal()
方法进行转换:
def contextMenuEvent(self, event):
gp = event.globalPos()
lp = self.list.viewport().mapFromGlobal(gp)
index = self.list.indexAt(lp)
if index.isValid():
self.indexMenu.exec_(gp)
else:
self.nonIndexMenu.exec_(gp)
我试图在用户右键单击 QListView 中的项目时弹出上下文菜单,如果用户在任何项目之外(任何空白处)右键单击则弹出不同的上下文菜单.我发现我在执行 indexAt 命令时收到的索引不准确,我不知道为什么。
我将 QListView 初始化为它自己的 class:
class RBKDataTypesTab(QWidget):
def __init__(self):
super().__init__()
self.models = []
grid = QGridLayout()
self.list = QListView()
self.list.clicked.connect(self.list_item_selected)
grid.addWidget(self.list, 0, 0, -1, 8)
self.table = QTableView()
self.indexMenu = QMenu()
self.indexMenu.addAction('Add DataType', self.addDataType)
self.indexMenu.addAction('Remove DataType', self.removeDataType)
self.nonIndexMenu = QMenu()
self.nonIndexMenu.addAction('Add DataType', self.addDataType)
grid.addWidget(self.table, 0, 2, -1, -1)
self.setLayout(grid)
此时,列表为空。当打开文件以设置模型时,我还有其他功能,它将数据加载到屏幕上。
这是我的上下文菜单事件:
def contextMenuEvent(self, event):
index = self.list.indexAt(event.pos())
print(index.data())
if(index.isValid()):
event.accept()
self.indexMenu.exec_(event.globalPos())
else:
event.accept()
self.nonIndexMenu.exec_(event.globalPos())
假设我有三个通用项目:
- item1
- item2
- item3
感谢 print 语句,我可以知道当我单击 QListView 中 item1 的顶部 1/4 时,它正在返回 item1。但是,如果我单击 item1 的底部 3/4,它将返回 item2。 item2 和 item3 的逻辑相同,只有 item3 的底部 3/4 returns None,因此返回错误的上下文菜单。
谁能帮我理解为什么会这样?我认为它与 event.pos() 有关,但我不知道是什么。
谢谢!!
event.pos()
的坐标是相对于拥有 contextMenuEvent()
方法的小部件而言的,在您的情况下它是相对于 window 但 indexAt()
方法需要相对于视图 (QListView) 的 viewport()
的坐标,因此您必须使用 mapFromGlobal()
方法进行转换:
def contextMenuEvent(self, event):
gp = event.globalPos()
lp = self.list.viewport().mapFromGlobal(gp)
index = self.list.indexAt(lp)
if index.isValid():
self.indexMenu.exec_(gp)
else:
self.nonIndexMenu.exec_(gp)