I have two QTableViews inside a QMainWindow and I want to create a context menu on one of them and later another context menu on the other one.
Creating the context menu and define actions works so far. But the context menu pops up everywhere inside the whole application. I don't know how to limit it to only one specific table. I think it has to do with contextMenuEvent() which is a member of QMainWindow, but I don't know how to change this part. Trying to create a custom class that inherits QTableView didn't work, because I'm not sure where to start.
Here's what I tried:
The populate_table_1() and populate_table_2() methods are only for filling some data into the tables. The get_selected_item_TV1() method gets the necessary data from a row of table_1. The delete_file() method is an example for what I want do when calling the delete action from the contextMenuEvent() method. This code works so far, but I want the context menu to popup only if I right-click on a row of table_1 and that it don't appear at all when right-clicking elsewhere.
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
data_1 = ["file_name", "file_infos"]
data_2 = ["other_stuff_1", "other_stuff_2"]
class Ui_MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle("MyApp")
self.resize(450, 280)
centralwidget = QWidget(self)
#]===================================================================[#
# table_1
table_1 = QTableView(
centralwidget,
selectionBehavior=QAbstractItemView.SelectRows,
editTriggers=QAbstractItemView.NoEditTriggers
)
# table_1 models
self.modelTV1 = QStandardItemModel(0, 2, centralwidget)
self.modelTV1.setHorizontalHeaderLabels(["column 1", "column 2"])
table_1.setModel(self.modelTV1)
self.selectionModelTV1 = table_1.selectionModel()
#]===================================================================[#
# table_2
table_2 = QTableView(
centralwidget,
selectionBehavior=QAbstractItemView.SelectRows,
editTriggers=QAbstractItemView.NoEditTriggers,
)
# table_2 models
self.modelTV2 = QStandardItemModel(0, 2, centralwidget)
self.modelTV2.setHorizontalHeaderLabels(["column 1", "column 2"])
table_2.setModel(self.modelTV2)
self.selectionModelTV2 = table_2.selectionModel()
v_Layout1 = QVBoxLayout()
v_Layout1.addWidget(table_1)
v_Layout1.addWidget(table_2)
gridLayout = QGridLayout(centralwidget)
gridLayout.addLayout(v_Layout1, 0, 0, 1, 1)
self.setCentralWidget(centralwidget)
def populate_table_1(self):
self.modelTV1.setRowCount(0)
for item in data_1:
self.modelTV1.insertRow(0)
for i, text in enumerate(data_1):
self.modelTV1.setItem(0, i, QStandardItem(text))
def populate_table_2(self):
self.modelTV2.setRowCount(0)
for item in data_2:
self.modelTV2.insertRow(0)
for i, text in enumerate(data_2):
self.modelTV2.setItem(0, i, QStandardItem(text))
def contextMenuEvent(self, event):
self.contextMenu = QMenu(self)
deleteAction = QAction("Delete", self)
self.contextMenu.addAction(deleteAction)
deleteAction.triggered.connect(lambda: self.delete_file(event))
self.contextMenu.popup(QCursor.pos())
def get_selected_item_TV1(self):
# get the row's text from the first column in table_1
listed_items = self.selectionModelTV1.selectedRows()
for index in listed_items:
selected_item = index.data()
return f"table_1 - row_{index.row()} - {selected_item}"
def delete_file(self, event):
item = self.get_selected_item_TV1()
print(f"Deleting: {item}")
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
mainUI = Ui_MainWindow()
mainUI.populate_table_1()
mainUI.populate_table_2()
mainUI.show()
sys.exit(app.exec_())