Qt Delete Selected Row in Qtableview

Qt Delete selected row in QTableView

You can use the bool QAbstractItemModel::removeRow(int row, const QModelIndex & parent = QModelIndex()) functionality for this.

Here you can find an example for all this.

Also, here is an inline quote from that documentation:

removeRows()

Used to remove rows and the items of data they contain
from all types of model. Implementations must call beginRemoveRows()
before inserting new columns into any underlying data structures, and
call endRemoveRows() immediately afterwards.

The second part of the task would be to connect the button's clicked signal to the slot executing the removal for you.

How to delete multiple rows in a QTableView widget?

Why is always one row not deleted when I select multiple rows and what
do I need to change to delete all selected rows?

The problem is caused by removing a row by resetting the positions, for example, say that you remove 3,4,5, first remove 3, then 4 becomes 3, and 5 becomes 4, then you eliminate 4, remove the 4 current so that the initial 4 is not deleted.

QModelIndex are temporary indexes that are not notified if the positions change, instead QPersistentModelIndex if they are notified so you must use them to get the row even if it changes.

def delete(self):
if self.tableView.selectionModel().hasSelection():
indexes =[QPersistentModelIndex(index) for index in self.tableView.selectionModel().selectedRows()]
for index in indexes:
print('Deleting row %d...' % index.row())
self.QSModel.removeRow(index.row())
else:
print('No row selected!')

How do I automatically select the next row after the deletion is
complete so that I could delete the whole table by repeatedly clicking
the Delete Row(s) button?

to select a new row you must set some item of that row as active through the setCurrentIndex() method of QTableView, in this example I calculate the last row and with that I get the QPersistentModelIndex of an item of the next row, after deleting I convert it to QModelIndex and I use it in the previous method.

def delete(self):
if self.tableView.selectionModel().hasSelection():
indexes =[QPersistentModelIndex(index) for index in self.tableView.selectionModel().selectedRows()]
maxrow = max(indexes, key=lambda x: x.row()).row()
next_ix = QPersistentModelIndex(self.QSModel.index(maxrow+1, 0))
for index in indexes:
print('Deleting row %d...' % index.row())
self.QSModel.removeRow(index.row())
self.tableView.setCurrentIndex(QModelIndex(next_ix))
else:
print('No row selected!')

Is there a built-in method that allows me to either connect the
QPushButton or its action to DEL/BACKSPACE key-presses? I.e., I want
DEL/BACKSPACE key-presses to trigger delete().

to get the keyboard events you must overwrite the keyPressEvent method, this event happens as a QKeyEvent object that has a key method that returns the key pressed, verify if it is the desired key and if it is, then call delete()

def keyPressEvent(self, event):
if event.key() in (Qt.Key_Backspace, Qt.Key_Delete):
self.delete()
QDialog.keyPressEvent(self, event)

How to delete row/rows from a qtableview in 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())

Qt table widget, button to delete row

To remove the row we must first get the row, if we are inserting widgets inside the cells the currentRow() method will not return the appropriate row, in many cases it will return the row of the last cell without widget that has been selected.

For that reason you must opt for another solution, for this case we will use the indexAt() method of QTableWidget, but for this we need to know the position in pixels of the cell. when one adds a widget to a cell, this cell will be the parent of the widget, so we can access from the button to the cell using the parent() method, and then get the position of the cell with respect to the QTableWidget and use it in indexAt(). To access the button we will use the sender().

When the current cell is removed the focus is lost, a possible solution is to place the focus again in another cell.

void MainWindow::deleteThisLine()
{
//sender(): QPushButton
QWidget *w = qobject_cast<QWidget *>(sender()->parent());
if(w){
int row = ui->tableWidget->indexAt(w->pos()).row();
ui->tableWidget->removeRow(row);
ui->tableWidget->setCurrentCell(0, 0);
}
}

Insert and remove row in pyqts QTableView using the QAbstractTableModel

I marked for you the lines I made the changes. Try it:

import sys
#import time
from PyQt5.QtWidgets import QApplication, QMainWindow, QToolBar, QAction, QTableView
from PyQt5.QtCore import (QSize, Qt, QAbstractTableModel, pyqtSlot, pyqtSignal,
QThread, QModelIndex)


class QTableThread(QThread):
sig1 = pyqtSignal(list)

def __init__(self):
super(QTableThread, self).__init__()
self.count = 4

def run(self):
for i in range(20):
self.sig1.emit(["This", "is", "test", self.count])
self.count += 1
self.msleep(500) # !!!


class TableModel(QAbstractTableModel):
def __init__(self, _data):
super(TableModel, self).__init__()
self._data = _data

def data(self, index, role):
if role == Qt.DisplayRole:
return self._data[index.row()][index.column()]

def rowCount(self, index=QModelIndex()): # +
return 0 if index.isValid() else len(self._data) # +

def columnCount(self, index=QModelIndex()):
return len(self._data[0])

# +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
def insertRows(self, new_row, position, rows, parent=QModelIndex()):
position = (position + self.rowCount()) if position < 0 else position
start = position
end = position + rows - 1

if end <= 8:
self.beginInsertRows(parent, start, end)
self._data.append(new_row)
self.endInsertRows()
return True
else:
self.beginInsertRows(parent, start, end)
self._data.append(new_row)
self.endInsertRows()
self.removeRows(0, 0)
return True

def removeRows(self, position, rows, parent=QModelIndex()):
start, end = position, rows
self.beginRemoveRows(parent, start, end)
del self._data[start:end + 1]
self.endRemoveRows()
return True
# +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


class Table(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.resize(800, 600)
self.setMinimumSize(QSize(800, 600))

self.table = QTableView()
self.setCentralWidget(self.table)

toolbar = QToolBar("Toolbar")
con = QAction("Connect", self)
con.triggered.connect(self.updateTable)
discon = QAction("Disconnect", self)
discon.triggered.connect(self.terminateThread)

toolbar.addAction(con)
toolbar.addAction(discon)
self.addToolBar(toolbar)

self.thread = None # +++

def updateTable(self):
print("Connect")
data = [
["This", "is", "test", 1],
["This", "is", "test", 2],
["This", "is", "test", 3],
]
self.model = TableModel(data)
self.table.setModel(self.model)

self.thread = QTableThread()
# self.thread.sig1.connect(self.model.addRow) # ---
self.thread.sig1.connect(lambda new_row: self.model.insertRows(new_row, -1, 1)) # +++
self.thread.start()

def terminateThread(self):
if self.thread and self.thread.isRunning(): # +++
self.thread.terminate()


if __name__ == "__main__":
app = QApplication(sys.argv)
win = Table()
win.show()
sys.exit( app.exec_() )

Sample Image

How to remove row from Qtableview and SQLite using with QSqlTableModel?

Calling deleteRowFromTable was useless, because you didn't select any table; note that you should not use that function anyway (from the docs:

This is a low-level method that operates directly on the database and should not be called directly. Use removeRow() or removeRows() to delete values.

You should use QSqlTableModel instead of QSqlQueryModel. Remember that if any change happens from code, the model requires to be repopulated using select() in order to the view to be correctly updated.

class UI(QMainWindow):
def __init__(self):
super(UI, self).__init__()
# ...

DBModel = QSqlTableModel()
DBModel.setTable("card")
DBModel.select()

self.tableView.setModel(DBModel)

self.dbmodel = DBModel
self.pushButton.clicked.connect(self.removeRow)

def removeRow(self):
selected = self.tableView.selectedIndexes()

rows = set(index.row() for index in selected)
rows = list(rows)
rows.sort()
first = rows[0]

self.dbmodel.removeRow(first)
self.dbmodel.select()


Related Topics



Leave a reply



Submit