【问题标题】:Create different context menus on several QTableViews在几个 QTableViews 上创建不同的上下文菜单
【发布时间】:2020-07-10 08:33:24
【问题描述】:

我在QMainWindow 中有两个QTableViews,我想在其中一个上创建一个上下文菜单,然后在另一个上创建另一个上下文菜单。

到目前为止,创建上下文菜单和定义操作都有效。但是上下文菜单会在整个应用程序中随处弹出。我不知道如何将其限制在一个特定的表中。我认为这与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_())

【问题讨论】:

    标签: python pyqt5 contextmenu qtableview


    【解决方案1】:

    有很多选择:

    • 检测当鼠标按下时它在某个区域,例如第一个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())
      
    • 为每个QTableView实现contextMenuEvent方法:

      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}")
      

    【讨论】:

      猜你喜欢
      • 2016-08-19
      • 2017-05-13
      • 1970-01-01
      • 2011-04-08
      • 1970-01-01
      • 2022-01-03
      • 1970-01-01
      • 2014-07-27
      • 1970-01-01
      相关资源
      最近更新 更多