【问题标题】:How to delete row/rows from a qtableview in pyqt?如何从pyqt中的qtableview中删除行/行?
【发布时间】:2016-10-13 16:02:13
【问题描述】:

我正在为我的 qtableview 使用 QStandardItemModel。

import ui_my_viewlogs
import os
from PyQt4 import QtCore, QtGui

class my_viewlogs(QtGui.QDialog, ui_my_viewlogs.Ui_viewlogs):
    def __init__(self):
        super(my_viewlogs, self).__init__()
        self.setupUi(self)
        self.model = QtGui.QStandardItemModel()
        self.tableView.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.header_names = ['abc', 'def', 'ghi', 'kjl', 'mno', 'pqr']
        self.model.setHorizontalHeaderLabels(self.header_names)
        self.tableView.verticalHeader().setVisible(False)
        self.tableView.setShowGrid(False)
        self.selectionModel = self.tableView.selectionModel()
        self.tableView.customContextMenuRequested.connect(self.open_menu)
        self.tableView.setModel(self.model)
        self.tableView.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)

    def open_menu(self, position):
        menu = QtGui.QMenu()
        remove_selected_item_icon = QtGui.QIcon()
        remove_selected_item_icon.addPixmap(QtGui.QPixmap(":/images      /Images/deleteSelected.png"), QtGui.QIcon.Normal, QtGui.QIcon.On)
        remove_selected_item = menu.addAction(remove_selected_item_icon, "Remove selected item(s) ")
        if action == remove_selected_item:           
            model = self.model
            indices = self.tableView.selectionModel().selectedRows() 
            for index in sorted(indices):
                model.removeRow(index.row(), QtCore.QModelIndex()) 

当我尝试删除所选行时(即 model.removeRow() )我收到错误“TypeError: argument 1 of QAbstractItemModel.removeRow() has an invalid type”。

我已经搜索了很多在 pyqt 的 qtableview 中删除选定行的正确方法。但是,我无法删除选定的行。

您能否分享一个在 pyqt 的 qtableview 中删除选定行的示例代码?

【问题讨论】:

  • 为什么要将QtCore.QModelIndex 类传递给removeRow?如果有的话,它应该是一个实例,即。 QtCore.QModelIndex(),但这是默认设置,因此最好将其全部删除。
  • @Tim 即使我使用 QtCore.QModelIndex() 或将其全部删除...我仍然遇到相同的错误 ....
  • @tim 感谢您纠正我的拼写错误。

标签: python qt pyqt pyqt4 qtableview


【解决方案1】:

方法 model.removeRow(index.row()) 删除选中的行。

model = self.model
    indices = self.tableView.selectionModel().selectedRows() 
    for index in sorted(indices):
        model.removeRow(index.row()) 

在索引变量中我们得到选定的行,然后我们删除该行。

用于删除我们选择的 tableview 中的多行:

index_list = []                                                          
for model_index in self.tableView.selectionModel().selectedRows():       
    index = QtCore.QPersistentModelIndex(model_index)         
    index_list.append(index)                                             

for index in index_list:                                      
     self.model.removeRow(index.row())                                                               

【讨论】:

    【解决方案2】:

    在 C++ 中:

    QModelIndexList indices = myTable->selectionModel()->selectedRows();
    
    for (int i=indices.count()-1; i>=0; --i)
    {
        QModelIndex index = indices.at(i);
        myTable->removeRow(index.row());
    }
    

    你必须从列表的底部到顶部,否则你的索引会搞砸。

    【讨论】:

      【解决方案3】:

      如果有人在实施Anuj Bhasin's 答案后仍在寻找答案,因为上述解决方案在许多情况下无法按预期工作。

      原因:

      • 当您删除行索引(例如[0,1,2])并从0 -> 1 -> 2 开始删除时,只会删除第0 行和第2 行!
      • 删除第一项会将剩余的行向上移动,使 row 1row 2 分别为 row 0row 1,因此当您下次删除第 1 行时,第 2 行(以前)将被删除,因为它现在是第 1 行。

      我有办法解决这个问题:

      传递要删除的行,例如从 5 行中删除 [0,3]

      def setSel(selected: List[int], table_widget: QTableWidget):
          """
          Select all rows for the given index range
          """
          table_widget.setSelectionMode(QAbstractItemView.MultiSelection)
          for i in selected:
              table_widget.selectRow(i)
      

      然后以 table_widget:QTableWidget 作为参数调用remove_row_all_table()

      def remove_row_all_table(table_widget):
          """
          Select and Delete rows from table widget
          """
          table_widget: QTableWidget
          selected_rows = table_widget.selectionModel().selectedRows()
          if selected_rows:
              row_indices = []
              for row_index in selected_rows:
                  row_indices.append(row_index.row())
              row_indices.sort(key=lambda x: -1 * x)
              print(row_indices)
              for row in row_indices:  # sorted in descending order
                  print(f"row count:{table_widget.rowCount()}, deleting index:{row}")
                  table_widget.removeRow(row)
          print()
      

      这个答案的总结是:你必须开启MultiSelection模式,并以相反的顺序删除,即从高索引到低索引,这样我在答案开头提到的依赖就不会发生。

      【讨论】:

      • 这个答案是针对 qtablewidget 的,它与 qtableview 不同。
      【解决方案4】:

      使用 reversed() 对我来说效果很好。

              indices = self.tag_table.selectionModel().selectedRows()
      
              # Must delete in reverse order
              for each_row in reversed(sorted(indices)):
                  self.tag_table.removeRow(each_row.row())
      

      【讨论】:

        【解决方案5】:

        我知道这是一个较老的问题,但我认为这更简洁并且可以解决问题。

        def delete_record1(self, model, view):
            """Delete rows with currently selected cells and/or selected rows of the model"""
            rows = [model_index.row() for model_index in view.selectedIndexes()]
            
            rows.sort(reverse=True)
        
            for i in rows:
                model.removeRow(i)
            
            model.submitAll()
            model.select()    
        

        谁能告诉我这种方法的缺陷是什么?

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-11-21
          • 2018-02-02
          • 1970-01-01
          • 2018-06-15
          • 1970-01-01
          • 2013-10-01
          相关资源
          最近更新 更多