我的程序有一个树形视图,与允许添加和删除元素的模型相连。当当前选定项更改时,我必须执行与新选定项相关的操作(例如显示图像)。我使用
如何避免
模型中有三个兄弟:image0、image1和image2,在0、1、2行。
selectionModel()
中的currentChanged()
作为更改信号。除了一种情况外,一切正常:当父项有多个子项并且我删除行0时,endRemoveRows()
会警告我无效索引(-1,0),并且视图的新0行未正确突出显示为已选择:但是,对该项的操作被正确执行。
更一般地说,我认为在删除项目后,currentChanged()
信号总是发出指向删除前的模型的索引,这会导致在我删除第一行时在视图中出现问题。如何避免
endRemoveRows()
警告无效索引,并确保位于行0的新项目正确突出显示?模型中有三个兄弟:image0、image1和image2,在0、1、2行。
- 测试1) 在树形视图中,Image2为青色。如果我删除Image2:
- 新索引行为1
- 在树形视图中,Image1被选中(但是是灰色的)
- 测试2) 在树形视图中,Image0为青色。如果我删除Image0:
- endRemoveRows警告无效索引(-1,0)
- 新索引行为1
- 打印出新的0行项目,但是视图中没有任何项目被选中(甚至不是灰色的)
- 由于视图中没有选择任何项目,所以我每次点击都会产生currentChanged()。所以如果我点击新的0行,就会再次执行相关的打印操作
最小工作示例
如果您在pycharm上运行以下代码,请转到编辑配置并激活“在输出控制台中模拟终端”。
from PyQt5.QtGui import QStandardItemModel
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtGui import QStandardItem
from PyQt5.QtCore import Qt
from PyQt5 import QtWidgets, uic, QtCore
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.treeView = QtWidgets.QTreeView(self.centralwidget)
self.treeView.setGeometry(QtCore.QRect(140, 100, 241, 391))
self.treeView.setObjectName("treeView")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(180, 60, 151, 23))
self.pushButton.setObjectName("pushButton")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "deleteSelectedItem"))
def mySetup(self):
self.myModel = QStandardItemModel(0,1)
self.myModel.setHeaderData(0, Qt.Horizontal, "File name")
self.myModel.parent = self
image0 = QStandardItem()
image0.setText("image0.png")
image1 = QStandardItem()
image1.setText("image1.png")
image2 = QStandardItem()
image2.setText("image2.png")
folder = QStandardItem()
folder.setText("folderA")
folder.appendRows([image0,image1,image2])
self.myModel.appendRow(folder)
self.treeView.setModel(self.myModel)
self.treeView.selectionModel().currentChanged.connect(self.model_current_item_changed)
self.pushButton.clicked.connect(self.erase_selected_treeitem)
def model_current_item_changed(self, new, old):
print("new:", new.row())
print("old", old.row())
#print("current:", self.treeView.selectionModel().currentIndex().row())
if new.isValid() and not self.treeView.model().itemFromIndex(new).hasChildren(): # show item image
print("Is image:" , self.treeView.model().itemFromIndex(new).text())
else:
print("Is Folder:", self.treeView.model().itemFromIndex(new).text())
def erase_selected_treeitem(self):
index = self.treeView.selectionModel().currentIndex()
if index is not None and index.isValid():
parent = index.parent()
self.myModel.beginRemoveRows(parent, index.row(), index.row())
self.myModel.removeRow(index.row(), parent)
self.myModel.endRemoveRows()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
ui.mySetup()
MainWindow.show()
sys.exit(app.exec_())
QAbstractItemModel.createIndex
中的一个bug导致的。即别名,即为两个不同的元素返回相同的内部指针/ID,在删除过程中导致了这个警告。一旦我修复了它,警告就消失了。 - undefined