PySide Qt 在叶项中插入行并更新视图
PySide Qt insert row at leaf item and update view
我有这个主要工作的代码,使用户能够将项目添加到树结构。只要您不向叶项(没有子项的项)添加项,这就可以正常工作。
如果项目没有子项目,那么在第一次添加子项目时,视图根本不会更新。您可以通过卷起父项并重新展开它来使视图更新。或者,添加第二个子项目会导致视图更新(您可以看到两个项目都已添加)。
如何在将第一个子项添加到叶项后更新视图?
更新:您也可以双击新的父项,将显示其子项,但不会显示扩展小部件。似乎没有发生的是在满足上述条件之一之前不会显示小的展开项目小部件。
from PySide import QtCore, QtGui
import sys
model_data = [
[1, [2, [3, 4]]],
[5, [6, 7]],
[8, [9]],
[10]
]
class MyData:
def __init__(self, number, parent=None):
''''''
self.number = number
self.children = []
self.parent = parent
if parent is not None:
parent.addChild(self)
def row(self):
''''''
row = None
if self.parent is None:
row = 0
else:
for i, item in enumerate(self.parent.children):
if item == self:
row = i
break
return row
def addChild(self, item):
''''''
self.children.append(item)
item.parent = self
class TreeModel(QtCore.QAbstractItemModel):
def __init__(self, top, *args, **kwargs):
''''''
super(TreeModel, self).__init__(*args, **kwargs)
self.__top = top
def index(self, row, column, parent=QtCore.QModelIndex()):
''''''
if parent.isValid():
parent_node = parent.internalPointer()
node = parent_node.children[row]
index = self.createIndex(row, column, node)
else:
index = self.createIndex(row, column, self.__top)
return index
def parent(self, index):
''''''
if index.isValid():
node = index.internalPointer()
parent = node.parent
if parent is None:
parent_index = QtCore.QModelIndex()
else:
parent_index = self.createIndex(parent.row(), 0, parent)
else:
parent_index = QtCore.QModelIndex()
return parent_index
def rowCount(self, index=QtCore.QModelIndex()):
''''''
node = index.internalPointer()
if node is None:
count = 1
else:
count = len(node.children)
return count
def columnCount(self, index=QtCore.QModelIndex()):
''''''
return 1
def data(self, index, role=QtCore.Qt.DisplayRole):
''''''
if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole:
node = index.internalPointer()
data = str(node.number)
else:
data = None
return data
def addChild(self, index, child):
self.beginInsertRows(index, self.rowCount(index), self.rowCount(index)+1)
parent = index.internalPointer()
parent.addChild(child)
self.endInsertRows()
class Window(QtGui.QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.build_model()
self.add_item_action = QtGui.QAction('New &Item', self)
self.add_item_action.triggered.connect(self.add_item)
self.view = QtGui.QTreeView()
self.view.setModel(self.model)
self.setCentralWidget(self.view)
self.show()
def build_model(self):
def recurse(parent, children_data):
for child_data in children_data:
if isinstance(child_data, list):
recurse(child, child_data)
else:
child = MyData(child_data, parent=parent)
top = MyData(0)
for i, next in enumerate(model_data):
recurse(top, next)
self.model = TreeModel(top)
def add_item(self):
''''''
index = self.view.currentIndex()
new_item = MyData(0)
self.model.addChild(index, new_item)
def contextMenuEvent(self, event):
''''''
contextMenu = QtGui.QMenu()
contextMenu.addAction(self.add_item_action)
contextMenu.exec_(event.globalPos())
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = Window()
sys.exit(app.exec_())
模型不会总是正确更新,除非它知道布局发生了变化。所以试试这个:
def addChild(self, index, child):
...
self.endInsertRows()
self.layoutChanged.emit()
我有这个主要工作的代码,使用户能够将项目添加到树结构。只要您不向叶项(没有子项的项)添加项,这就可以正常工作。
如果项目没有子项目,那么在第一次添加子项目时,视图根本不会更新。您可以通过卷起父项并重新展开它来使视图更新。或者,添加第二个子项目会导致视图更新(您可以看到两个项目都已添加)。
如何在将第一个子项添加到叶项后更新视图?
更新:您也可以双击新的父项,将显示其子项,但不会显示扩展小部件。似乎没有发生的是在满足上述条件之一之前不会显示小的展开项目小部件。
from PySide import QtCore, QtGui
import sys
model_data = [
[1, [2, [3, 4]]],
[5, [6, 7]],
[8, [9]],
[10]
]
class MyData:
def __init__(self, number, parent=None):
''''''
self.number = number
self.children = []
self.parent = parent
if parent is not None:
parent.addChild(self)
def row(self):
''''''
row = None
if self.parent is None:
row = 0
else:
for i, item in enumerate(self.parent.children):
if item == self:
row = i
break
return row
def addChild(self, item):
''''''
self.children.append(item)
item.parent = self
class TreeModel(QtCore.QAbstractItemModel):
def __init__(self, top, *args, **kwargs):
''''''
super(TreeModel, self).__init__(*args, **kwargs)
self.__top = top
def index(self, row, column, parent=QtCore.QModelIndex()):
''''''
if parent.isValid():
parent_node = parent.internalPointer()
node = parent_node.children[row]
index = self.createIndex(row, column, node)
else:
index = self.createIndex(row, column, self.__top)
return index
def parent(self, index):
''''''
if index.isValid():
node = index.internalPointer()
parent = node.parent
if parent is None:
parent_index = QtCore.QModelIndex()
else:
parent_index = self.createIndex(parent.row(), 0, parent)
else:
parent_index = QtCore.QModelIndex()
return parent_index
def rowCount(self, index=QtCore.QModelIndex()):
''''''
node = index.internalPointer()
if node is None:
count = 1
else:
count = len(node.children)
return count
def columnCount(self, index=QtCore.QModelIndex()):
''''''
return 1
def data(self, index, role=QtCore.Qt.DisplayRole):
''''''
if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole:
node = index.internalPointer()
data = str(node.number)
else:
data = None
return data
def addChild(self, index, child):
self.beginInsertRows(index, self.rowCount(index), self.rowCount(index)+1)
parent = index.internalPointer()
parent.addChild(child)
self.endInsertRows()
class Window(QtGui.QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.build_model()
self.add_item_action = QtGui.QAction('New &Item', self)
self.add_item_action.triggered.connect(self.add_item)
self.view = QtGui.QTreeView()
self.view.setModel(self.model)
self.setCentralWidget(self.view)
self.show()
def build_model(self):
def recurse(parent, children_data):
for child_data in children_data:
if isinstance(child_data, list):
recurse(child, child_data)
else:
child = MyData(child_data, parent=parent)
top = MyData(0)
for i, next in enumerate(model_data):
recurse(top, next)
self.model = TreeModel(top)
def add_item(self):
''''''
index = self.view.currentIndex()
new_item = MyData(0)
self.model.addChild(index, new_item)
def contextMenuEvent(self, event):
''''''
contextMenu = QtGui.QMenu()
contextMenu.addAction(self.add_item_action)
contextMenu.exec_(event.globalPos())
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = Window()
sys.exit(app.exec_())
模型不会总是正确更新,除非它知道布局发生了变化。所以试试这个:
def addChild(self, index, child):
...
self.endInsertRows()
self.layoutChanged.emit()