Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

PySide2 context menu not showing for QTableView



  • Hello,
    I am trying to implement a context menu for a QTableView but it doesn't seem to show up.

    I have my tableview setup as an instance attribute

    self.dbView = QTableView(self)
    self.dbView.setContextMenuPolicy(Qt.CustomContextMenu)
    self.dbView.customContextMenuRequested.connect(self.showContextMenu)
    self.dbView.verticalHeader().hide()
    

    This is where I set the model

    def listDiverse(self, view):
            if not self.openDb():
                msgBox = QMessageBox();
                msgBox.setWindowTitle("Eroare baza de date");
                msgBox.setInformativeText("Nu s-a putut face conexiunea la bza de date!");
                msgBox.setStandardButtons(QMessageBox.Ok);
                msgBox.setDefaultButton(QMessageBox.Ok);
                msgBox.resize(500, 200)
                ret = msgBox.exec_();
                print("Error opening database")
                return
            model = QSqlQueryModel()
            model.setQuery("select id, name, quantity, unit, price, data_entry from diverse")
            model.setHeaderData(0, Qt.Horizontal, "ID")
            model.setHeaderData(1, Qt.Horizontal, "Nume")
            model.setHeaderData(2, Qt.Horizontal, "Cantitate")
            model.setHeaderData(3, Qt.Horizontal, "U.M.")
            model.setHeaderData(4, Qt.Horizontal, "Pret")
            model.setHeaderData(5, Qt.Horizontal, "Data Modificare")
            view.setModel(model)
            view.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
            view.hideColumn(0)
            view.setSelectionBehavior(QAbstractItemView.SelectRows)
            view.selectRow(0)
            if self.db.isOpen():
                self.closeDb()
    

    And here is the function where I make the menu and show it

    def showContextMenu(self, pos):
            print("pos " + str(pos))
            index = self.dbView.indexAt(pos)
            menu = QMenu()
            menu.addAction(QAction("Sterge"))
            menu.popup(self.dbView.viewport().mapToGlobal(pos))
    

    You can see that I also print the position of the click and it gives coordinates, but the menu won't show up itself.
    Any help is much appreciated.


  • Lifetime Qt Champion

    @adutzu89 I think the problem is that popup() is non blocking call (I'm actually not 100% sure), so your menu simply goes out of scope and is deleted. Try to use exec() instead of popup().



  • Hi @jsulm ,
    Thanks for taking your time to help, I tried your solution and while it doesn't show the menu I can only interact with the view on the second click.
    Guessing it opens the menu, but it isn't visible, somehow.


  • Lifetime Qt Champion

    @adutzu89 Did you try to show it without providing coordinates? Just to see whether it is related?



  • @jsulm same thing, I also tried to check isVisible() and returns true. But I am looking on entire screen and nothing.
    I forgot to mention I am working on KDE Neon, which is based on Ubuntu 18.04. I will try and fire up other machines and see the result on them, to see if it's a Linux/window manager problem.

    Will return shortly with result.



  • @jsulm so I tried on MacOS and has the same issue.

    On Windows 10 I cannot install PySide2, I get the following error:

    ERROR: Could not find a version that satisfies the requirement pyside2 (from versions: none)
    ERROR: No matching distribution found for pyside2
    

    I get the error when trying to install using pip:

    pip install --index-url=https://download.qt.io/official_releases/QtForPython/ pyside2
    

    and

    pip install PySide2
    

    Tried with Python2 and Python3.8, tried a couple of solutions.
    Will try to find a solution in a few hours.


  • Lifetime Qt Champion

    Hi,

    Can you provide a minimal complete code sample that reproduces that behaviour ?



  • Hi @SGaist ,
    Thanks for joining the help :D.
    So I tried to minimize the code as much as I could, didn't trimmed much from the imports though:

    # This Python file uses the following encoding: utf-8
    import sys
    from PySide2.QtWidgets import QApplication, QMainWindow, QWidget, QPushButton, QVBoxLayout, QLabel, QTableView
    from PySide2.QtWidgets import QHBoxLayout, QGroupBox, QHeaderView, QDialog, QLineEdit, QMessageBox, QAbstractItemView
    from PySide2.QtWidgets import QMenu, QAction
    from PySide2.QtCore import QSettings, Qt, Signal, Slot, QModelIndex
    from PySide2.QtGui import QStandardItemModel, QStandardItem
    
    
    class MainWindow(QMainWindow):
        closeDialog = Signal()
        def __init__(self):
            QMainWindow.__init__(self)
            self.dbView = QTableView(self)
            self.dbView.setContextMenuPolicy(Qt.CustomContextMenu)
            self.dbView.customContextMenuRequested.connect(self.showContextMenu)
            self.dbView.verticalHeader().hide()
            self.dbViewContextMenu = QMenu()
            self.dbViewContextMenu.addAction(QAction("Sterge"))
    
            mainWidget = QWidget(self)
            mainLayout = QVBoxLayout()
            mainWidget.setLayout(mainLayout)
            self.addItems(mainLayout)
            self.setCentralWidget(mainWidget)
            self.listDiverse(self.dbView)
    
        def addItems(self, layout):
            label = QLabel(self)
            label.setText("Test pentru PostgreSQL cu Qt for Python")
            layout.addWidget(label)
            label.show()
            layout.addWidget(self.dbView)
            self.dbView.show()
    
        def closeEvent(self, event):
            settings = QSettings("SDC", "PGExample")
            settings.setValue("geometry", self.saveGeometry())
            settings.setValue("windowState", self.saveState())
            QMainWindow.closeEvent(self, event)
    
        def readSettings(self):
            settings = QSettings("SDC", "PGExample")
            self.restoreGeometry(settings.value("geometry"))
            self.restoreState(settings.value("windowState"))
    
        def listDiverse(self, view):
            model = QStandardItemModel (4, 4)
            for row in range(4):
                for column in range(4):
                    item = QStandardItem("row %d, column %d" % (row, column))
                    model.setItem(row, column, item)
            view.setModel(model)
            view.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
            view.setSelectionBehavior(QAbstractItemView.SelectRows)
    
    
        def showContextMenu(self, pos):
            print("pos " + str(pos))
            index = self.dbView.indexAt(pos)
    #        self.dbViewContextMenu.popup(self.dbView.viewport().mapToGlobal(pos))
            self.dbViewContextMenu.exec_(self.dbView.viewport().mapToGlobal(pos))
            print("isVisible " + str(self.dbViewContextMenu.isVisible()))
    
    
    if __name__ == "__main__":
        app = QApplication([])
        window = MainWindow()
        window.show()
        window.resize(800,600)
        window.readSettings()
        sys.exit(app.exec_())
    
    

    Managed to finally install PySide2 on Windows 10 x64, with Python3.7 x86.



  • @jsulm , @SGaist I tested that sample code in Windows 10 and I experience the same issue.
    The menu is there, but not showing up on the screen.


  • Lifetime Qt Champion

    An educated guess: your action has no parent and is destroyed early.

    Change self.dbViewContextMenu.addAction(QAction("Sterge")) to either:

    • self.dbViewContextMenu.addAction("Sterge")
      or
    • self.dbViewContextMenu.addAction(QAction("Sterge", self))

    Don't forget to connect the created action to some slot to do something.



  • @SGaist said in PySide2 context menu not showing for QTableView:

    An educated guess: your action has no parent and is destroyed early.

    Change self.dbViewContextMenu.addAction(QAction("Sterge")) to either:

    • self.dbViewContextMenu.addAction("Sterge")
      or
    • self.dbViewContextMenu.addAction(QAction("Sterge", self))

    Don't forget to connect the created action to some slot to do something.

    It worked, cheers!
    Yes, made to QAction("Sterge") for testing purposes, but since I couldn't manage to make it work it didn't made sense to try and make a functional action.

    Thanks a lot for all your help.


  • Lifetime Qt Champion

    You're welcome !

    Since you have it working now, please mark the thread as solved using the "Topic Tools" button so that other forum users may know a solution has been found :)


Log in to reply