上下文菜单在不应该打开的时候打开(if...elif)

Context menu is opening when it shouln't (if...elif)

我有一个包含 8 列的 QTableWidget,我希望上下文菜单仅在第一列(第 0 列)中打开,因为在其余列中我使用右键单击进行不同的操作。

当我第一次启动程序时,一切正常:例如,如果我先在第 3 列的单元格中单击鼠标右键,它会执行它应该执行的操作(从单元格值中减去 1),但它不会打开上下文菜单,完美。

但是在我首先右键单击第 0 列以打开上下文菜单(它工作正常)之后,如果我返回到第 3 列并右键单击...上下文菜单打开!它也执行它应该执行的操作(从单元格值中减去 1)!

这是我使用的代码:

class Table(QtWidgets.QTableWidget):
            cellExited = QtCore.pyqtSignal(int, int)
            itemExited = QtCore.pyqtSignal(QtWidgets.QTableWidgetItem)

    def __init__(self,*args,**kwargs):
            QtWidgets.QTableWidget.__init__(self,*args,**kwargs)
            self.setItemDelegate(ReadOnlyDelegate(self))
            self._last_index = QtCore.QPersistentModelIndex()
            self.viewport().installEventFilter(self)
            self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)

            self.popMenu = QtWidgets.QMenu(self)
            self.popMenu.addAction(QtWidgets.QAction('Action 1', self))
            self.popMenu.addAction(QtWidgets.QAction('Action 2', self))
            self.popMenu.addAction(QtWidgets.QAction('Action 3', self))

    def mousePressEvent(self,event):
        it = self.itemAt(event.pos())
        print(it.column())    #DEBUG
        if it.column()>0:
            if event.button() == QtCore.Qt.LeftButton:
                it.setText(str(round(float(it.text()) + 1,2)))
            elif event.button() == QtCore.Qt.RightButton:
                it.setText(str(round(float(it.text()) - 1,2)))
        elif it.column() == 0 and event.button() == QtCore.Qt.RightButton:
            print(it.column() == 0)    #DEBUG
            print(event.button() == QtCore.Qt.RightButton)    #DEBUG        
            self.customContextMenuRequested.connect(self.on_context_menu)

    def on_context_menu(self, point):
        self.popMenu.exec_(self.viewport().mapToGlobal(point))

self.customContextMenuRequested.connect(self.on_context_menu) 表示您正在将事件 customContextMenuRequested 连接到方法 self.on_context_menu。每次事件发生时(可能是每次右键单击),都会调用该方法。

第一次右键单击第 0 列时,将事件连接到方法。此后每次右键单击都会调用该方法。

你想要的是直接调用self.on_context_menu,如:

def mousePressEvent(...):
   ....
   elif it.column() == 0 ... :
        self.on_context_menu()

将事件处理程序 (on_context_menu) 连接到另一个事件处理程序 (mousePressEvent) 中的事件 (customContextMenuRequested) 似乎是非正统的。

相反,您可以在 __init__ 方法中连接事件。这意味着将 self.customContextMenuRequested.connect(self.on_context_menu) 移动到 __init__。 然后在 on_context_menu 中,您应该检查请求了哪个上下文菜单,并且仅在它是第一列时才显示它:

def on_context_menu(self, point):
    # the ... should be replaced by code that gets the column on which the event occurred
    column == ...
    if column == 0:
        self.popMenu.exec_(self.viewport().mapToGlobal(point))

(我实际上不知道如何获取 on_context_menu 中的列)

然后在 mousePressEvent 中,您不再需要整个 elif 部分。