简体   繁体   中英

How to delete row/rows from a qtableview in pyqt?

I am using QStandardItemModel for my qtableview.

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

here when I am trying to delete the row selected(ie model.removeRow() ) I am getting a error" TypeError: argument 1 of QAbstractItemModel.removeRow() has an invalid type".

I have searched a lot for the correct way of deleting a selected row/rows in qtableview of pyqt. However, I am not able to delete the selected row/rows.

Can you please share a sample code for deleting selected row/rows in qtableview of pyqt?

the method model.removeRow(index.row()) removes the row selected.

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

in the indices variable we get the selected row, then we delete the row.

For deleting multiple rows in our selection of 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())                                                               

If someone is still looking for an answer after implementing Anuj Bhasin's answer because the above solution will not work in many cases as expected.

Reason:

  • When you delete row index (for example [0,1,2] ), and you start to delete from 0 -> 1 -> 2 , then only row 0 and row 2 will be deleted!
  • Deleting the First item will shift the remaining rows up , making row 1 and row 2 as row 0 and row 1 respectively, thus when you next delete row 1, row 2 (previously) will be deleted as it is now row 1.

I have a solution to this:

Pass rows you want to delete for example from 5 rows delete [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)

then call remove_row_all_table() with table_widget: QTableWidget as parameter

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

Summary of this answer is: You have to turn on MultiSelection mode and Delete in reverse order, ie from higher index to lower index, so that the dependency that I mentioned at the beginning of the answer does not occur.

In C++:

QModelIndexList indices = myTable->selectionModel()->selectedRows();

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

You have to go from the bottom to the top of the list or your indexing will be screwed up.

This works just fine for me using the 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())

I know this is a bit of an older question, but I think this is more concise and does the trick.

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

Can anybody advise what the pitfalls of this approach is?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM