2

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.

Geni-sama
  • 307
  • 5
  • 15

1 Answers1

5

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)
musicamante
  • 41,230
  • 6
  • 33
  • 58
  • How on earth. I was trying to accomplish this for over a day now and you just did it for like 5 mins?? Anyway, I tested this and this works. Upon checking this, I still don't understand why my viewport didn't work, but I will study this and I might get it soon. I have to say your coding style is so elegant. I have seen similar code example as this while searching for answers and tried it but didn't work, perhaps I went wrong somewhere. Thanks to this I'm gonna study this for now for maybe few hours until I understand it. – Geni-sama Sep 21 '20 at 14:25
  • 1
    Thanks, i was learning about signals and your example cleared alot of confusions. I was calling the eventhandler which was wrong. +1 – Elan Sep 21 '20 at 14:30
  • 1
    @Geni-sama you're welcome. For future reference, always try to provide minimal *reproducible* examples; minimal doesn't mean "just some snippets", but just provide only what's necessary to keep the code reproducible, without unnecessary parts that are possibly unrelated to the matter at hand. I don't know what you did wrong in your case, as you didn't provide the parts that would actually allow us to *reproduce* the issue. We cannot assume what you do or what you don't, until you show us exactly what you did. – musicamante Sep 21 '20 at 14:45
  • You are very very right. I'll keep your advice for the next time I seek help again. I really wish I didn't erase my previous codes so I could better understand what I did wrong. What only saddens me here though is that I wasn't able to solve this myself, that I got desperate into solving it and sought for help. But I really do appreciate your help, it meant a lot, my code works now. I'm gonna try this method again in another app so I can understand it better. Again, THANK YOU VERY MUCH!! – Geni-sama Sep 21 '20 at 14:58