Создайте разные контекстные меню на нескольких QTableView - PullRequest
1 голос
/ 30 марта 2020

У меня есть два QTableView внутри QMainWindow, и я хочу создать контекстное меню для одного из них, а затем другое контекстное меню для другого.

Создание контекстного меню и определение действий пока работает. Но контекстное меню появляется во всем приложении. Я не знаю, как ограничить его только одной конкретной таблицей c. Я думаю, что это связано с contextMenuEvent(), который является членом QMainWindow, но я не знаю, как изменить эту часть. Попытка создать собственный класс, который наследует QTableView, не сработала, потому что я не уверен, с чего начать.

Вот что я попробовал:

Методы populate_table_1() и populate_table_2() предназначены только для заполнения некоторых данных в таблицах. Метод get_selected_item_TV1() получает необходимые данные из строки table_1. Метод delete_file() является примером того, что я хочу сделать при вызове действия удаления из метода contextMenuEvent(). Этот код работает до сих пор, но я хочу, чтобы контекстное меню всплыло только в том случае, если я щелкнул правой кнопкой мыши строку table_1 и что оно вообще не появляется при щелчке правой кнопкой мыши в другом месте.

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_())

1 Ответ

2 голосов
/ 30 марта 2020

Есть много альтернатив:

  • Обнаружить, что при нажатии мыши она находится в определенной области, например, в первом QTableView. В этом случае виджет должен быть доступен в contextMenuEvent (), поэтому вы должны изменить table_1 на self.table_1 и затем использовать underMouse ():

    def contextMenuEvent(self, event):
        if self.table_1.underMouse():
            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())
    
  • Реализовать метод contextMenuEvent для каждого QTableView:

    class TableView(QTableView):
        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.selectionModel().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}")
    

    , а затем вы должны изменить table_1 = QTableView(... на table_1 = TableView(...

  • Другой альтернативой является использование сигнала customContextMenuRequested, для этого вы должны включите флаг Qt :: CustomContextMenu:

    table_1 = QTableView(
        centralwidget,
        selectionBehavior=QAbstractItemView.SelectRows,
        editTriggers=QAbstractItemView.NoEditTriggers,
        contextMenuPolicy=Qt.CustomContextMenu
    )
    table_1.customContextMenuRequested.connect(self.on_customContextMenuRequested)
    
    def on_customContextMenuRequested(self):
        self.contextMenu = QMenu(self)
        deleteAction = QAction("Delete", self)
    
        self.contextMenu.addAction(deleteAction)
        deleteAction.triggered.connect(lambda: self.delete_file())
    
        self.contextMenu.popup(QCursor.pos())
    
    def delete_file(self):
        item = self.get_selected_item_TV1()
        print(f"Deleting: {item}")
    
...