QListView.indexAt in PyQt5 returning wrong index?

孤街浪徒 提交于 2021-01-28 14:51:56

问题


I'm trying to pop up a context menu when a user right-clicks on an item in a QListView and a different context menu if the user right-clicks outside of any of the items (any of the whitespace). What I'm finding is that the index I'm receiving when performing the indexAt command is not accurate, and I can't figure out why.

I initialize the QListView as its own 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)

At this point, the list is empty. I have other functions when a file is opened to set the model, which loads the data on the screen.

Here is my contextMenuEvent:

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())

Let's assume I have three generic items:

  • item1
  • item2
  • item3

Thanks to the print statement, I can tell when I click the top 1/4 of item1 in the QListView, it is returning item1. If I click in the bottom 3/4 of item1, however, it is returning item2. Same logic for item2 and item3, only the bottom 3/4 of item3 returns None, hence returning the wrong context menu.

Can someone help me understand why this is happening? I'm thinking it has something to do with event.pos(), but I don't know what.

Thanks!!


回答1:


The coordinates of the event.pos() are with respect to the widget that owns the contextMenuEvent() method, in your case it is with respect to the window but the indexAt() method expects coordinates with respect to the viewport() of the view(QListView) so You have to do a transformation using the mapFromGlobal() method:

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)


来源:https://stackoverflow.com/questions/59174609/qlistview-indexat-in-pyqt5-returning-wrong-index

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!