【问题标题】:How to add a right click action (not menu) to QTableWidget's cells如何向 QTableWidget 的单元格添加右键单击操作(不是菜单)
【发布时间】:2018-11-13 20:01:53
【问题描述】:

我目前有一个带有不同单元格的 QTableWidget。当我左键单击一个单元格时,我希望其上的数字加 1,如果我右键单击,我希望其上的数字减 1。

第一部分我用没问题

self.(widget_name).cellClicked.connect(self.addone)

问题在于右键单击。有内置的方法吗?我怎样才能实现它?我尝试从 QTableWidgets 创建自己的 Table 类并覆盖 mousePressEvent 但没有用(单击单元格没有做任何事情,它甚至没有选择单元格)。还尝试了 eventFilter 并没有。有关我在这两种情况下使用的确切代码,请参见下文。

对于 mousePressEvent:

class Table(QtWidgets.QTableWidget):

    def __init__(self,parent=None):
        QtWidgets.QTableWidget.__init__(self,parent)

    def mousePressEvent(self,QMouseEvent):
        if QMouseEvent.button() == QtCore.LeftButton:
            print('left') #FOR DEBUGGING
            row = self.currentRow()
            column = self.currentColumn()
            new_text = round(float(self.item(row,column).text()) + 1,2)
            self.item(row,column).setText(str(new_text))          

        elif event.button() == QtCore.RightButton:
            print('right') #FOR DEBUGGING
            row = self.currentRow()
            column = self.currentColumn()
            new_text = round(float(self.item(row,column).text()) - 1,2)
            self.item(row,column).setText(str(new_text)) 

对于事件过滤器:

class Table(QtWidgets.QTableWidget):
    def __init__(self,parent=None):
        QtWidgets.QTableWidget.__init__(self,parent)
        self.installEventFilter(self)

    def eventFilter(self,QObject,event):
        if event.type() == QtCore.QEvent.MouseButtonPress:
            if event.button() == QtCore.LeftButton:
                print('left') #FOR DEBUGGING
                row = self.currentRow()
                column = self.currentColumn()
                new_text = round(float(self.item(row,column).text()) + 1,2)
                self.item(row,column).setText(str(new_text))          

            elif event.button() == QtCore.RightButton:
                print('right') #FOR DEBUGGING
                row = self.currentRow()
                column = self.currentColumn()
                new_text = round(float(self.item(row,column).text()) - 1,2)
                self.item(row,column).setText(str(new_text))

对于两者(创建表)

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        self.centralwidget = QtWidgets.QWidget(self)
        ....
        self.parameters = Table(self.centralwidget)
        ...
...

调试文本(打印“左”或“右”)也不会出现在控制台中。

【问题讨论】:

    标签: python pyqt pyqt5 qtablewidget


    【解决方案1】:

    当您覆盖一个方法时,它总是调用父方法,因为它可能正在执行其他类型的任务,而您会忽略它。另一方面,如果我们这样做,代理将被激活以编辑文本,这是不想要的,所以我们建立一个没有发布者返回的新代理,如下所示:

    import sys
    from PyQt5 import QtWidgets, QtGui, QtCore
    
    class ReadOnlyDelegate(QtWidgets.QStyledItemDelegate):
        def createEditor(self, *args, **kwargs):
            return
    
    class Table(QtWidgets.QTableWidget):
        def __init__(self, *args, **kwargs):
            QtWidgets.QTableWidget.__init__(self, *args, **kwargs)
            self.setItemDelegate(ReadOnlyDelegate(self))
    
        def mousePressEvent(self, event):
            if event.button() == QtCore.Qt.LeftButton:
                it = self.itemAt(event.pos())
                new_text = round(float(it.text()) + 1,2)
                it.setText(str(new_text))          
    
            elif event.button() == QtCore.Qt.RightButton:
                it = self.itemAt(event.pos())
                new_text = round(float(it.text()) - 1,2)
                it.setText(str(new_text))     
            QtWidgets.QTableWidget.mousePressEvent(self, event)
    
    class MainWindow(QtWidgets.QMainWindow):
        def __init__(self, parent=None):
            QtWidgets.QMainWindow.__init__(self, parent)
    
            table = Table(5, 5)
            self.setCentralWidget(table)
            for i in range(5):
                for j in range(5):
                    item = QtWidgets.QTableWidgetItem("{}".format(i*j))
                    table.setItem(i, j, item)
    
    if __name__=='__main__':
        import sys
        app = QtWidgets.QApplication(sys.argv)
        window = MainWindow()
        window.show()
        sys.exit(app.exec())
    

    【讨论】:

    • 谢谢!这完美地工作,但我不明白为什么。能否请您更深入地解释一下?非常感谢您的帮助!
    • @LeonBrasero 你不明白我回答的哪一部分?
    • "代理将被激活以编辑文本,这是不想要的,所以我们建立一个没有发布者返回的新代理,如下所示:"我假设代理是我创建的用于覆盖父方法的代码,但我不明白这句话的其余部分。再次感谢 eyllanesc。
    • @LeonBrasero 委托不是我做的覆盖父母的代码,查看以下了解:doc.qt.io/qt-5/model-view-programming.html,委托是class ReadOnlyDelegate(QtWidgets.QStyledItemDelegate): ...self.setItemDelegate(ReadOnlyDelegate(self))
    【解决方案2】:

    试试看:

    class Table(QtWidgets.QTableWidget):
        def mousePressEvent(self, event):
            if event.button() == QtCore.Qt.LeftButton:
                print('left')                 # FOR DEBUGGING
                row = self.currentRow()
                column = self.currentColumn()
                new_text = round(float(self.item(row,column).text()) + 1,2)
                self.item(row,column).setText(str(new_text))          
    
            elif event.button() == QtCore.Qt.RightButton:
                print('right')                 # FOR DEBUGGING
                row = self.currentRow()
                column = self.currentColumn()
                new_text = round(float(self.item(row,column).text()) - 1,2)
                self.item(row,column).setText(str(new_text)) 
    

    【讨论】:

    • 唯一的变化是 event.button() 和 QtCore.Qt。正确的?我确实尝试过但仍然无法正常工作,甚至没有打印调试。另外,请注意:我看到我错误地将 OP QtWidgets.QTableWidgetItem 放在 init 中,而它应该是 QtWidgets.QTableWidget。刚刚修复了这个问题(并编辑了 OP)但仍然无法正常工作:(
    • 更正:它现在确实打印调试文本,但没有别的,它甚至没有选择我单击的单元格。谢谢!一步一步来!
    • 更正 2:我刚刚发现,如果我只是单击一个单元格,什么都不会发生,但是如果我单击一个单元格并在其自身内稍微拖动鼠标,该单元格将变得有点——已选中(因此背景不会像往常一样变为蓝色但保持白色,但单元格的框架会变成点,就好像它确实被选中了一样)。之后,如果我单击表格中的任何位置,它会添加或减去数字。
    猜你喜欢
    • 2019-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-20
    • 1970-01-01
    • 1970-01-01
    • 2013-07-04
    相关资源
    最近更新 更多