Caeta
Caeta

Reputation: 461

Create a context menu with PyQt5

I'm trying to make a context menu and I saw some tuts in which they program the next code for example:

import sys
from PyQt5.QtWidgets import QMainWindow, qApp, QMenu, QApplication


class Example(QMainWindow):

    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):
        self.setGeometry(300, 300, 300, 200)
        self.setWindowTitle('Context menu')
        self.show()

    def contextMenuEvent(self, event):
        cmenu = QMenu(self)

        newAct = cmenu.addAction("New")
        openAct = cmenu.addAction("Open")
        quitAct = cmenu.addAction("Quit")
        action = cmenu.exec_(self.mapToGlobal(event.pos()))

        if action == quitAct:
            qApp.quit()


def main():
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

I tried to implement in my code which have 2 modules but don't work:

main.py

import win0 as w0
from PyQt5.QtWidgets import QMainWindow, QApplication, QMenu

class Main(QMainWindow, w0.Ui_win0):
    win0 = None
    __win0_ui = None

    def __init__(self):
        self.win0 = QMainWindow()
        self.__win0_ui = w0.Ui_win0()
        self.__win0_ui.setupUi(self.win0)
        self.win0.show()

if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    main = Main()
    app.setStyle("Fusion")
    sys.exit(app.exec_())

win0.py

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QTableWidget, QFrame, QMenu, QMainWindow, qApp

class Table(QTableWidget, QMainWindow):

    def contextMenuEvent(self, event):
        cmenu = QMenu(self)
        newAct = cmenu.addAction("New")
        openAct = cmenu.addAction("Open")
        quitAct = cmenu.addAction("Quit")
        action = cmenu.exec_(self.mapToGlobal(event.pos()))

        if action == quitAct:
            qApp.quit()        

class Ui_win0(object):
    def setupUi(self, win0):
        win0.setObjectName("win0")
        win0.resize(703, 757)
        win0.setStyleSheet("background-color: rgba(29, 29, 29);"
                           "\ncolor: rgb(171, 171, 171);")
        self.centralwidget = QtWidgets.QWidget(win0)
        self.centralwidget.setObjectName("centralwidget")


        self.table1 = Table(self.centralwidget)
        
        # Code...

        self.retranslateUi(win0)
        QtCore.QMetaObject.connectSlotsByName(win0)

    def retranslateUi(self, win0):
        # Code...

I don't paste all the code for don't make it too long but i wanted implement the example in the Table class because i want to expand some options or others depending that if the cursor is over the table list or in other place of the window.

What i'm doing wrong?

EDIT 1 -------------------------------------------------------------------------- For more clarity, the idea it's the next

enter image description here

The white boxes represent the context menu of the right click in differents places of the window

Upvotes: 1

Views: 4785

Answers (1)

musicamante
musicamante

Reputation: 48231

I'm going to provide a "template code", since what was provided is almost unusable for various reasons (wrong inheritance, unnecessary object layers, unrequired functions and implementations).

In the following example, I'm using a mix of two of the possible approaches to create menu events:

class Table(QtWidgets.QTableWidget):
    def contextMenuEvent(self, event):
        menu = QtWidgets.QMenu()
        index = self.indexAt(event.pos())
        someAction = menu.addAction('')
        if index.isValid():
            someAction.setText('Selected item: "{}"'.format(index.data()))
        else:
            someAction.setText('No selection')
            someAction.setEnabled(False)
        anotherAction = menu.addAction('Do something')

        res = menu.exec_(event.globalPos())
        if res == someAction:
            print('first action triggered')


class Example(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        central = QtWidgets.QWidget()
        self.setCentralWidget(central)
        layout = QtWidgets.QHBoxLayout(central)
        self.table = Table(10, 4)
        layout.addWidget(self.table)
        layout.addStretch()

        central.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        central.customContextMenuRequested.connect(self.emptySpaceMenu)

    def emptySpaceMenu(self):
        menu = QtWidgets.QMenu()
        menu.addAction('You clicked on the empty space')
        menu.exec_(QtGui.QCursor.pos())


if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    example = Example()
    example.show()
    sys.exit(app.exec_())

As you can see, most of the structure you used was stripped away as unnecessary or redundant. This is a very important aspect: while keeping a highly explicit and "verbose" object structure usually allows better abstraction, overdoing so only makes things unnecessarily complex and very confusing, even to the programmer.

Upvotes: 5

Related Questions