如何在 PyQt5 中捕获 QTableWidget 上的左右鼠标单击事件?

Posted

技术标签:

【中文标题】如何在 PyQt5 中捕获 QTableWidget 上的左右鼠标单击事件?【英文标题】:How to catch left and right mouse click event on QTableWidget in PyQt5? 【发布时间】:2020-09-21 13:03:51 【问题描述】:

我创建了一个QTableWidget 使用PyQt5openpyxlVSCode 中加载excel,我无法分别捕捉/获取鼠标左键和右键。左键单击将单元格内容复制到剪贴板,右键单击单元格以粘贴剪贴板中的内容。 基本上,左键单击复制单元格-> 保存到剪贴板-> 右键单击​​粘贴到单元格。

App的分步流程: 1 - 左键单击这些单元格中的任何一个将复制内容 2 - 复制的内容将保存/粘贴到剪贴板区域 (QLineEdit/QLabel) 3 - 右键单击​​任何这些单元格将粘贴剪贴板中的内容 4 - 以矩形显示 QTableWidget 的区域

这些是我尝试过但不起作用的一些代码:

# def tablewidget_clicked(self):
    #     self.mclick = self.tableWidget.mousePressEvent
    #     print(str(self.mclick))
        # self.leftclick = QtCore.Qt.LeftButton
        # print(str(self.leftclick))  # Displays 1
        # self.rightclick = QtCore.Qt.RightButton
        # print(str(self.rightclick)) # Displays 2
        # self.midclick = QtCore.Qt.MiddleButton
        # print(str(self.midclick)) # Displays
        # if QtGui.QMouseEvent.button(QtCore.Qt.MouseButton): #== QtCore.Qt.LeftButton:         
        #     print('hello')
        # else:
        #     print('hi')
        
    def eventFilter(self, source, event):
        if event.type() == QtGui.QMouseEvent.MouseButtonPress:
            if event.button() == QtCore.Qt.LeftButton:
                print('hello')
                return True
        else:
            return False

即使为self.tableWidget 创建视口也不起作用。

self.tablevport = self.tableWidget.viewport()
self.tablevport.installEventFilter(self)
self.tablevport.mousePressEvent()

到目前为止,这些代码下面可以工作(作为测试),但同时读取左键和右键。

self.tableWidget.cellClicked.connect(self.tablewidget_clicked)
def tablewidget_click(self):
     if QtCore.Qt.LeftButton:
          print('hello')
     if QtCore.Qt.RightButton:
          print('hi')

如果我能在这个应用程序中获得一个代码模式来实现我的目标,那将对我有很大帮助。我没有通过谷歌和 youtube 搜索。 最后,我相信或者至少我认为我在这里有很多缺陷,比如编码风格,将 QTableWidget 与其他类分开,很长的代码,也许我可以从其他 .py 文件中导入。但我仍在学习并以某种方式一点一点地改进。我确实希望我的问题的这个介绍可以很容易理解。

【问题讨论】:

请不要将代码添加为图片。 我认为如果我包含这些不起作用的代码,可能会引起一些人的困惑。但我可以编辑它。 请提供minimal, reproducible example,可能与您对事件过滤器所做的测试有关。 【参考方案1】:

使用cellClicked 信号是不够的,因为它只适用于鼠标左键。此外,您的函数实际上并没有检查任何内容,因为 Qt.LeftButtonQt.RightButton 都是常量,您实际上是在做这样的事情:

    def tablewidget_click(self):
        if 1:
            print('hello')
        if 2:
            print('hi')

使用事件过滤器是正确的选择,但我不明白您为什么要调用 self.mousePressEvent():QMouseEvent 应该作为参数,您通常应该手动调用事件处理程序。此外,调用self.tableWidget.viewport() 不会“创建”视口,它只是返回它,因为所有基于滚动区域的小部件都有一个。

这是一个工作示例:

class Test(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        layout = QtWidgets.QVBoxLayout(self)
        self.clipboardLabel = QtWidgets.QLabel()
        layout.addWidget(self.clipboardLabel)
        self.tableWidget = QtWidgets.QTableWidget(10, 10)
        layout.addWidget(self.tableWidget)
        self.tableWidget.viewport().installEventFilter(self)

    def eventFilter(self, source, event):
        if event.type() == QtCore.QEvent.MouseButtonPress:
            if event.button() == QtCore.Qt.LeftButton:
                index = self.tableWidget.indexAt(event.pos())
                if index.data():
                    self.clipboardLabel.setText(index.data())
            elif event.button() == QtCore.Qt.RightButton:
                index = self.tableWidget.indexAt(event.pos())
                if index.isValid():
                    item = self.tableWidget.itemFromIndex(index)
                    if not item:
                        item = QtWidgets.QTableWidgetItem()
                        self.tableWidget.setItem(index.row(), index.column(), item)
                    item.setText(self.clipboardLabel.text())
        return super().eventFilter(source, event)

【讨论】:

到底怎么样。我试图完成这个已经超过一天了,而你只做了 5 分钟?无论如何,我对此进行了测试,并且有效。检查后,我仍然不明白为什么我的视口不起作用,但我会研究这个,我可能很快就会得到它。我不得不说你的编码风格是如此优雅。我在搜索答案时看到了与此类似的代码示例并尝试过但没有奏效,也许我在某个地方出错了。多亏了这一点,我现在要研究这个可能几个小时,直到我理解它。 谢谢,我正在学习信号,你的例子消除了很多困惑。我正在调用错误的事件处理程序。 +1 @Geni-sama 不客气。为了将来参考,请始终尝试提供最少的可重现示例;最小并不意味着“只是一些 sn-ps”,而只是提供保持代码可重复性所必需的内容,而没有可能与手头的问题无关的不必要部分。我不知道你在你的情况下做错了什么,因为你没有提供实际上允许我们重现问题的部分。在您向我们确切展示您所做的事情之前,我们无法假设您做了什么或没有做什么。 你说的非常非常正确。下次我再次寻求帮助时,我会保留您的建议。我真的希望我没有删除我以前的代码,这样我才能更好地理解我做错了什么。不过,这里唯一让我难过的是我自己无法解决这个问题,我不顾一切地想要解决它并寻求帮助。但我真的很感谢你的帮助,这意味着很多,我的代码现在可以工作了。我将在另一个应用程序中再次尝试此方法,以便更好地理解它。再次,非常感谢!

以上是关于如何在 PyQt5 中捕获 QTableWidget 上的左右鼠标单击事件?的主要内容,如果未能解决你的问题,请参考以下文章

PyQt5 - 如何在使用 QThread 时减少 CPU 使用率(低于 50%)?

Qt实现单击或双击QTableWidge/View表头进行排序

在pyqt5中的QWidget上实现dragMoveEvent?

PyQt5 表格行高

用PyQt5进行视频录制

如何在 PyQt5 中横向打印?