Solved 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. -
@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. -
@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. -
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.
-
-
An educated guess: your action has no parent and is destroyed early.
Change
self.dbViewContextMenu.addAction(QAction("Sterge"))
to either:self.dbViewContextMenu.addAction("Sterge")
orself.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")
orself.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.
-
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 :)