尝试弄清楚如何在正在编辑的QTableView中捕获行的麻烦已被取消。例如,如果我正在QTableView中编辑新插入的行并按ESC,则已按向上/向下箭头键,则需要删除该行,因为(在我看来)已被取消。如果用户单击该行,也适用。我真的不能发布任何代码,因为我不知道如何实现这样的东西。有什么想法吗?
答案 0 :(得分:0)
我有一个我想要的例子(至少对于按键问题而言)。从那里,您可以为点击问题执行类似的操作。
我的解决方案使用覆盖QItemDelegate
方法的自定义eventFilter
。此外,它使用的是天真的模型(因为您想使用QTableView),模型上使用layoutChanged
信号是由于示例的功能所致,请根据需要阅读文档以获取更合适的添加/删除数据功能需求。
希望有帮助。
示例ui:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'test.ui',
# licensing of 'test.ui' applies.
#
# Created: Wed Nov 7 16:10:12 2018
# by: pyside2-uic running on PySide2 5.11.0
#
# WARNING! All changes made in this file will be lost!
from PySide2 import QtCore, QtGui, QtWidgets
class Ui_Test(object):
def setupUi(self, Test):
Test.setObjectName("Test")
Test.resize(538, 234)
self.horizontalLayout = QtWidgets.QHBoxLayout(Test)
self.horizontalLayout.setObjectName("horizontalLayout")
self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setObjectName("gridLayout")
self.tableView = QtWidgets.QTableView(Test)
self.tableView.setObjectName("tableView")
self.gridLayout.addWidget(self.tableView, 0, 0, 1, 1)
self.addRow = QtWidgets.QPushButton(Test)
self.addRow.setObjectName("addRow")
self.gridLayout.addWidget(self.addRow, 0, 1, 1, 1)
self.horizontalLayout.addLayout(self.gridLayout)
self.retranslateUi(Test)
QtCore.QMetaObject.connectSlotsByName(Test)
def retranslateUi(self, Test):
Test.setWindowTitle(QtWidgets.QApplication.translate("Test", "Dialog", None, -1))
self.addRow.setText(QtWidgets.QApplication.translate("Test", "add row", None, -1))
涉及的实际类(我使用PySide2):
from PySide2 import QtWidgets, QtCore, QtGui
from _test import Ui_Test
class MyDialog(QtWidgets.QDialog):
def __init__(self, parent = None):
super(MyDialog, self).__init__(parent = parent)
self.ui = Ui_Test()
self.ui.setupUi(self)
self._model = MyModel([["first row 1 col", "first row 2"],["second row 1", "second row 2"]])
self.ui.tableView.setModel(self._model)
self.ui.addRow.clicked.connect(self._model.addRow)
self.ui.tableView.setItemDelegate(MyDelegate(self.ui.tableView))
# this is crucial: we need to be sure that the selection is single on the view
self.ui.tableView.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectItems)
self.ui.tableView.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
class MyModel(QtCore.QAbstractTableModel):
def __init__(self, table_data = None, parent = None):
super(MyModel, self).__init__(parent = parent)
if not table_data: self._data = []
self._data = table_data
def rowCount(self, parent = None):
return len(self._data)
def columnCount(self, parent = None):
return 2
def addRow(self):
self._data.append(["new item", "new item"])
self.layoutChanged.emit()
def removeRow(self, row):
if 0 <= row < self.rowCount():
del self._data[row]
self.layoutChanged.emit()
def data(self, index, role = QtCore.Qt.DisplayRole):
if index.isValid():
if role == QtCore.Qt.DisplayRole:
row = index.row()
col = index.column()
return self._data[row][col]
def setData(self, index, value, role = QtCore.Qt.EditRole):
if index.isValid():
if role == QtCore.Qt.EditRole:
row = index.row()
col = index.column()
self._data[row][col] = str(value)
return True
else:
return False
else:
return False
def flags(self, index):
return QtCore.Qt.ItemIsSelectable|QtCore.Qt.ItemIsEditable|QtCore.Qt.ItemIsEnabled
class MyDelegate(QtWidgets.QItemDelegate):
def __init__(self, parent = None):
super(MyDelegate, self).__init__(parent)
self.view = parent
def eventFilter(self, editor, event):
# there is a lot of checking in order to identify the desired situation
# and avoid errors
if isinstance(event, QtGui.QKeyEvent):
if event.type() == QtCore.QEvent.KeyPress:
if event.key() == QtCore.Qt.Key_Escape:
# we should have a list here of length one (due to selection restrictions on the view)
index = self.view.selectedIndexes()
if index:
if index[0].isValid():
row = index[0].row()
self.view.model().removeRow(row)
return super(MyDelegate, self).eventFilter(editor, event)
if __name__ == '__main__':
app = QtWidgets.QApplication()
diag = MyDialog()
diag.show()
app.exec_()