如何删除 QTableView 小部件中的多行?
How to delete multiple rows in a QTableView widget?
我想通过按下 QPushButton 来删除 QTableView 小部件中的行。该代码适用于单行,但是,当我 select 多行时,总是会遗漏一行。
这是我目前拥有的:
main.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>350</width>
<height>239</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QWidget" name="formLayoutWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>341</width>
<height>231</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="1">
<widget class="QPushButton" name="btnPopulate">
<property name="text">
<string>Populate Table</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QTableView" name="tableView">
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="btnDelete">
<property name="text">
<string>Delete Row(s)</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>
test.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys, os
from PyQt5 import uic, QtWidgets
from PyQt5.QtGui import QStandardItemModel
from PyQt5.QtWidgets import QDialog, QComboBox, QApplication, QHeaderView
class GUI(QDialog):
def __init__(self):
super(GUI, self).__init__()
dirname = os.path.dirname(os.path.abspath(__file__))
uic.loadUi(os.path.join(dirname,'main.ui'), self)
# buttons
self.btnPopulate.clicked.connect(self.populate)
self.btnDelete.clicked.connect(self.delete)
# table model
self.header = ['col1', 'col2', 'col3']
self.QSModel = QStandardItemModel()
self.QSModel.setColumnCount(3)
self.QSModel.setHorizontalHeaderLabels(self.header)
self.tableView.setModel(self.QSModel)
self.tableView.verticalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
def populate(self):
row = self.QSModel.rowCount()
for x in range(7):
self.QSModel.insertRow(row)
self.QSModel.setData(self.QSModel.index(row, 0), 'data' + str(x))
self.QSModel.item(row, 0).setEditable(True)
self.QSModel.setData(self.QSModel.index(row, 1), 'data' + str(x))
self.QSModel.item(row, 1).setEditable(True)
self.QSModel.setData(self.QSModel.index(row, 2), 'data' + str(x))
self.QSModel.item(row, 1).setEditable(True)
def delete(self):
if self.tableView.selectionModel().hasSelection():
indexes = self.tableView.selectionModel().selectedRows()
for index in sorted(indexes):
print('Deleting row %d...' % index.row())
self.QSModel.removeRow(index.row())
else:
print('No row selected!')
if __name__ == '__main__':
app = QApplication(sys.argv)
window = GUI()
window.show()
sys.exit(app.exec_())
我有以下问题:
- 为什么当我 select 多行时总是有一行没有被删除,我需要更改什么才能删除所有 select 行?
- 如何在删除完成后自动 select 下一行,以便我可以通过重复单击“删除行”按钮删除整个 table?
- 是否有内置方法允许我将 QPushButton 或其操作连接到 DEL/BACKSPACE 按键?即,我希望 DEL/BACKSPACE 按键触发 delete()。
Why is always one row not deleted when I select multiple rows and what
do I need to change to delete all selected rows?
问题是通过重置位置去掉一行导致的,比如你去掉3,4,5,先去掉3,然后4变成3,5变成4,然后你去掉4,去掉当前的4,这样开头的4就不会被删除。
QModelIndex
是临时索引,如果位置发生变化则不会收到通知,而是 QPersistentModelIndex
如果收到通知则必须使用它们来获取行,即使它发生变化。
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?
到select一个新行你必须通过QTableView
的setCurrentIndex()
方法将该行的一些项目设置为活动的,在这个例子中我计算最后一行并用它我得到下一行项目的 QPersistentModelIndex
,删除后我将其转换为 QModelIndex
并在前面的方法中使用它。
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().
要获取键盘事件,您必须覆盖 keyPressEvent
方法,此事件作为一个 QKeyEvent
对象发生,该对象具有一个 returns 按键方法,验证它是否是所需的密钥,如果是,则调用 delete()
def keyPressEvent(self, event):
if event.key() in (Qt.Key_Backspace, Qt.Key_Delete):
self.delete()
QDialog.keyPressEvent(self, event)
我想通过按下 QPushButton 来删除 QTableView 小部件中的行。该代码适用于单行,但是,当我 select 多行时,总是会遗漏一行。
这是我目前拥有的:
main.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>350</width>
<height>239</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QWidget" name="formLayoutWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>341</width>
<height>231</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="1">
<widget class="QPushButton" name="btnPopulate">
<property name="text">
<string>Populate Table</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QTableView" name="tableView">
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="btnDelete">
<property name="text">
<string>Delete Row(s)</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>
test.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys, os
from PyQt5 import uic, QtWidgets
from PyQt5.QtGui import QStandardItemModel
from PyQt5.QtWidgets import QDialog, QComboBox, QApplication, QHeaderView
class GUI(QDialog):
def __init__(self):
super(GUI, self).__init__()
dirname = os.path.dirname(os.path.abspath(__file__))
uic.loadUi(os.path.join(dirname,'main.ui'), self)
# buttons
self.btnPopulate.clicked.connect(self.populate)
self.btnDelete.clicked.connect(self.delete)
# table model
self.header = ['col1', 'col2', 'col3']
self.QSModel = QStandardItemModel()
self.QSModel.setColumnCount(3)
self.QSModel.setHorizontalHeaderLabels(self.header)
self.tableView.setModel(self.QSModel)
self.tableView.verticalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
def populate(self):
row = self.QSModel.rowCount()
for x in range(7):
self.QSModel.insertRow(row)
self.QSModel.setData(self.QSModel.index(row, 0), 'data' + str(x))
self.QSModel.item(row, 0).setEditable(True)
self.QSModel.setData(self.QSModel.index(row, 1), 'data' + str(x))
self.QSModel.item(row, 1).setEditable(True)
self.QSModel.setData(self.QSModel.index(row, 2), 'data' + str(x))
self.QSModel.item(row, 1).setEditable(True)
def delete(self):
if self.tableView.selectionModel().hasSelection():
indexes = self.tableView.selectionModel().selectedRows()
for index in sorted(indexes):
print('Deleting row %d...' % index.row())
self.QSModel.removeRow(index.row())
else:
print('No row selected!')
if __name__ == '__main__':
app = QApplication(sys.argv)
window = GUI()
window.show()
sys.exit(app.exec_())
我有以下问题:
- 为什么当我 select 多行时总是有一行没有被删除,我需要更改什么才能删除所有 select 行?
- 如何在删除完成后自动 select 下一行,以便我可以通过重复单击“删除行”按钮删除整个 table?
- 是否有内置方法允许我将 QPushButton 或其操作连接到 DEL/BACKSPACE 按键?即,我希望 DEL/BACKSPACE 按键触发 delete()。
Why is always one row not deleted when I select multiple rows and what do I need to change to delete all selected rows?
问题是通过重置位置去掉一行导致的,比如你去掉3,4,5,先去掉3,然后4变成3,5变成4,然后你去掉4,去掉当前的4,这样开头的4就不会被删除。
QModelIndex
是临时索引,如果位置发生变化则不会收到通知,而是 QPersistentModelIndex
如果收到通知则必须使用它们来获取行,即使它发生变化。
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?
到select一个新行你必须通过QTableView
的setCurrentIndex()
方法将该行的一些项目设置为活动的,在这个例子中我计算最后一行并用它我得到下一行项目的 QPersistentModelIndex
,删除后我将其转换为 QModelIndex
并在前面的方法中使用它。
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().
要获取键盘事件,您必须覆盖 keyPressEvent
方法,此事件作为一个 QKeyEvent
对象发生,该对象具有一个 returns 按键方法,验证它是否是所需的密钥,如果是,则调用 delete()
def keyPressEvent(self, event):
if event.key() in (Qt.Key_Backspace, Qt.Key_Delete):
self.delete()
QDialog.keyPressEvent(self, event)