Geni-sama
Geni-sama

Reputation: 317

How to catch left and right mouse click event on QTableWidget in PyQt5?

I have created a QTableWidget using PyQt5 and openpyxl to load excel in VSCode and I am having trouble to catch/get the left and right mouse click buttons separately. Left click to copy the cell content to the clipboard and Right click to cell to paste the content from the clipboard. Basically, left click copy cell -> save to clipboard -> right click paste to cell. enter image description here

Step by step process of the App:
1 - Left clicking any of these cells will copy the content
2 - The content copied will be saved/pasted here on the clipboard area (QLineEdit/QLabel)
3 - Right clicking on any of these cells will paste the content from the clipboard
4 - Shows the area of the QTableWidget in rectangle

These are some of the codes I tried but didn't work:

# 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

Even creating viewport for self.tableWidget didn't work.

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

So far these codes below work (as a test), but reads both left and right click at the same time.

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

It would help me a lot if I could get a code-pattern to achieve my goals here in this app. I had no luck in searching through google and youtube.
Lastly, I believe or at least I think I have so many flaws here like the coding style, separating QTableWidget to other class, pretty long codes which maybe I could have imported from other .py files. But I am still learning and somehow improving bit by bit. I do hope this presentation of my problem can be easily understood.

Upvotes: 2

Views: 10934

Answers (1)

musicamante
musicamante

Reputation: 48509

Using the cellClicked signal won't be enough, because it only works for the left mouse button. Also, your function doesn't actually check anything, as both Qt.LeftButton and Qt.RightButton are constants and you were practically doing something like this:

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

Using an event filter was the right choice, but I don't understand why you would call self.mousePressEvent(): a QMouseEvent is expected as argument, and you should normally not call event handlers manually. Also, calling self.tableWidget.viewport() does not "create" a viewport, it just returns it, as all scroll area based widgets have one.

Here's a working example:

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)

Upvotes: 5

Related Questions