Reputation: 195
I am trying to display a QMenu when a row is right clicked on a QTableWidget. The issue is that whenever the menu appears, It appears as a dot. Below you can find a minimal reproducible example.
import sys
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import (QApplication, QAction, QMenu, QTableWidget,
QAbstractItemView)
class PhotoSetTable(QTableWidget):
_menu = None
def __init__(self, parent=None):
super().__init__(parent)
self.setRowCount(0)
self.setColumnCount(2)
self.setHorizontalHeaderLabels(["Name", "Count"])
self.setSelectionBehavior(QAbstractItemView.SelectRows)
self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self._menu = self._generate_menu()
row_position = self.rowCount()
self.insertRow(row_position)
name_item = QtWidgets.QTableWidgetItem("asd")
name_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
count_item = QtWidgets.QTableWidgetItem("0")
count_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
self.setItem(row_position, 0, name_item)
self.setItem(row_position, 1, count_item)
#self._refresh()
@staticmethod
def _generate_menu():
menu = QMenu()
menu.addAction(QAction("Quit"))
menu.addSeparator()
menu.addAction(QAction("WUUU"))
menu.addSeparator()
return menu
def mousePressEvent(self, e):
super().mousePressEvent(e)
if e.buttons() == QtCore.Qt.RightButton:
item = self.itemAt(e.pos())
if item is not None:
self._menu.exec(e.globalPos())
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = PhotoSetTable()
ex.show()
sys.exit(app.exec_())
What is causing this behavior?
Upvotes: 1
Views: 2167
Reputation: 48479
The reason for which you only see a "point" is that you are actually seeing an empty menu, since you are creating QActions without parents.
QMenu.addAction(QAction*)
does not transfer ownership of the QAction to the menu (it behaves as QWidget.addAction
, as explained here, since QMenu is a QWidget descendent), which means that once the _generate_menu()
method returns, those action are "transferred" to Python's garbage collector (aka, deleted).
If, for any reason, you really need to create "standalone" QActions, add a parent to them (or make them a property of some persisent object, even by adding to another persistent object, like a list or a tuple), or just use menu.addAction(str)
as pointed out by MalloyDelacroix.
By the way, if you just set the menu as a parent, that will be enough:
menu.addAction(QAction("Quit", menu))
That said, at least according to your example, there's really no need to use a static method for this.
Upvotes: 2
Reputation: 2293
The problem is in adding QAction
to the generated context menu. Instead, try adding the menu items with the item name as a string as the first parameter, and the method it should call as the second.
@staticmethod
def _generate_menu():
menu = QMenu()
menu.addAction("Quit", lambda: print('quitting'))
menu.addSeparator()
menu.addAction("WUUU", method_name)
menu.addSeparator()
return menu
Upvotes: 2