Hiperfly
Hiperfly

Reputation: 178

How to add a right click action (not menu) to QTableWidget's cells

I currently have one QTableWidget with different cells. When I left-click on a cell I want the number on it to be increased by 1, and if I right-click I want the number to be decreased by 1.

For the first part there is no problem as I use

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

The problem comes with the right click. Is there a built in method for this? How can I achieve it? I tried creating my own Table class from QTableWidgets and overriding the mousePressEvent but didn't work (clicking around the cells doesn't do anything, it doesn't even select the cells). Also tried eventFilter and nothing. See below for the exact code I used in both situations.

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

For eventFilter:

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

For both (to create the table)

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

The debugging text (printing 'left' or 'right') doesn't appear in the console as well.

Upvotes: 2

Views: 4425

Answers (2)

eyllanesc
eyllanesc

Reputation: 243955

When you overwrite a method it always calls the parent's method since it could be doing other kinds of tasks and you would be omitting it. On the other hand if we do that, the delegate would be activated to edit the texts, and that is what is not wanted, so we establish a new delegate that no publisher returns as I show below:

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

Upvotes: 3

S. Nick
S. Nick

Reputation: 13651

Try it:

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

Upvotes: 2

Related Questions