这是带有自定义项目的其他SO问题QTreeView的链接,其中QTreeView示例。
请在这个例子中有人可以解释我,如何从treeview保存树结构。
我可以从中提取标签名称的QAbstractItemModel类以及可以再次加载的结构吗?
如果是这样,我如何访问节点?除了索引还有其他方法吗?
编辑(从链接):
import sys from PySide import QtGui, QtCore #------------------------------------------------------------------------------- # my test data class Icon(): def __init__(self, icon, tooltip): self.pixmap = QtGui.QPixmap(icon) self.tooltip = tooltip #------------------------------------------------------------------------------- # my test data class MyData(): def __init__(self, txt, parent=None): self.txt = txt self.tooltip = None self.parent = parent self.child = [] self.icon = [] self.index = None self.widget = None #--------------------------------------------------------------------------- def position(self): position = 0 if self.parent is not None: count = 0 children = self.parent.child for child in children: if child == self: position = count break count += 1 return position #--------------------------------------------------------------------------- # test initialization @staticmethod def init(): root = MyData("root") root.icon.append(Icon("icon.png", "ToolTip icon.png")) root.tooltip = "root tooltip" for i in range(0, 2): child1 = MyData("child %i" % (i), root) child1.icon.append(Icon("icon1.png", "ToolTip icon1.png")) child1.tooltip = "child1 tooltip" root.child.append(child1) for x in range(0, 2): child2 = MyData("child %i %i" % (i, x), child1) child2.icon.append(Icon("icon1.png", "ToolTip icon1.png")) child2.icon.append(Icon("icon2.png", "ToolTip icon2.png")) child2.tooltip = "child2 tooltip" child1.child.append(child2) return root #------------------------------------------------------------------------------- class TreeViewModel(QtCore.QAbstractItemModel): #--------------------------------------------------------------------------- def __init__(self, tree): super(TreeViewModel, self).__init__() self.__tree = tree self.__current = tree self.__view = None #--------------------------------------------------------------------------- def flags(self, index): flag = QtCore.Qt.ItemIsEnabled if index.isValid(): flag |= QtCore.Qt.ItemIsSelectable \ | QtCore.Qt.ItemIsUserCheckable \ | QtCore.Qt.ItemIsEditable \ | QtCore.Qt.ItemIsDragEnabled \ | QtCore.Qt.ItemIsDropEnabled return flag #--------------------------------------------------------------------------- def index(self, row, column, parent=QtCore.QModelIndex()): node = QtCore.QModelIndex() if parent.isValid(): nodeS = parent.internalPointer() nodeX = nodeS.child[row] node = self.__createIndex(row, column, nodeX) else: node = self.__createIndex(row, column, self.__tree) return node #--------------------------------------------------------------------------- def parent(self, index): node = QtCore.QModelIndex() if index.isValid(): nodeS = index.internalPointer() parent = nodeS.parent if parent is not None: node = self.__createIndex(parent.position(), 0, parent) return node #--------------------------------------------------------------------------- def rowCount(self, index=QtCore.QModelIndex()): count = 1 node = index.internalPointer() if node is not None: count = len(node.child) return count #--------------------------------------------------------------------------- def columnCount(self, index=QtCore.QModelIndex()): return 1 #--------------------------------------------------------------------------- def data(self, index, role=QtCore.Qt.DisplayRole): data = None return data #--------------------------------------------------------------------------- def setView(self, view): self.__view = view #--------------------------------------------------------------------------- def __createIndex(self, row, column, node): if node.index == None: index = self.createIndex(row, column, node) node.index = index if node.widget is None: node.widget = Widget(node) self.__view.setIndexWidget(index, node.widget) return node.index #------------------------------------------------------------------------------- class TreeView(QtGui.QTreeView): #--------------------------------------------------------------------------- def __init__(self, model, parent=None): super(TreeView, self).__init__(parent) self.setModel(model) model.setView(self) root = model.index(0, 0) self.setCurrentIndex(root) self.setHeaderHidden(True) #--------------------------------------------------------------------------- def keyPressEvent(self, event): k = event.key() if k == QtCore.Qt.Key_F2: self.__editMode() super(TreeView, self).keyPressEvent(event) #--------------------------------------------------------------------------- def __editMode(self): index = self.currentIndex() node = index.internalPointer() node.widget.editMode(True, True) #------------------------------------------------------------------------------- class Label(QtGui.QLabel): #--------------------------------------------------------------------------- def __init__(self, parent, text): super(Label, self).__init__(text) self.__parent = parent #--------------------------------------------------------------------------- def mouseDoubleClickEvent(self, event): #print("mouseDoubleClickEvent") if self.__parent is not None: self.__parent.editMode(True, True) else: super(Label, self).mouseDoubleClickEvent(event) #------------------------------------------------------------------------------- class LineEdit(QtGui.QLineEdit): #--------------------------------------------------------------------------- def __init__(self, parent, text): super(LineEdit, self).__init__(text) self.__parent = parent self.editingFinished.connect(self.__editingFinished) #--------------------------------------------------------------------------- def keyPressEvent(self, event): k = event.key() if k == QtCore.Qt.Key_Escape: print("ESC 2") self.__editingFinished(False) super(LineEdit, self).keyPressEvent(event) #--------------------------------------------------------------------------- def __editingFinished(self, bCopy=True): print("editingFinished") self.__parent.editMode(False, bCopy) #------------------------------------------------------------------------------- class Widget(QtGui.QWidget): #--------------------------------------------------------------------------- def __init__(self, node): super(Widget, self).__init__() self.autoFillBackground() self.__node = node self.__bEditMode = False self.__txt = None self.__create(self.__node, self.__bEditMode) #--------------------------------------------------------------------------- def __create(self, node, bEditMode): layout = QtGui.QHBoxLayout() for icon in node.icon: label = Label(None, node.txt) label.setPixmap(icon.pixmap) label.setToolTip("label tooltip %s %s" % (node.txt, icon.tooltip)) layout.addWidget(label) self.__changeTxt(layout, node, bEditMode, False) self.setLayout(layout) #--------------------------------------------------------------------------- def __changeTxt(self, layout, node, bEditMode, bCopy): if self.__txt is not None: if bCopy: node.txt = self.__txt.text() if isinstance(self.__txt, LineEdit): self.__txt.deselect() self.__txt.hide() layout.removeWidget(self.__txt) self.__txt = None if bEditMode: self.__txt = LineEdit(self, node.txt) self.__txt.setFrame(False) self.__txt.selectAll() QtCore.QTimer.singleShot(0, self.__txt, QtCore.SLOT('setFocus()')); else: self.__txt = Label(self, node.txt) self.__txt.setToolTip("Text tooltip %s %s" % (node.txt, node.tooltip)) layout.addWidget(self.__txt, 1) #--------------------------------------------------------------------------- def editMode(self, bEditMode, bCopy): if self.__bEditMode != bEditMode: self.__bEditMode = bEditMode layout = self.layout() self.__changeTxt(layout, self.__node, bEditMode, bCopy) #------------------------------------------------------------------------------- class MyTree(QtGui.QMainWindow): def __init__(self, parent=None): super(MyTree, self).__init__(parent) data = MyData.init() frame = QtGui.QFrame(); frame.setLayout( QtGui.QHBoxLayout() ); treeViewModel = TreeViewModel(data) treeView = TreeView(treeViewModel) frame.layout().addWidget( treeView ); self.setCentralWidget(frame) #------------------------------------------------------------------------------- def main(): app = QtGui.QApplication(sys.argv) form = MyTree() form.show() app.exec_() if __name__ == '__main__': main()
您的问题尚不清楚,因为您没有说要保存树形结构的形式。
假设您不太在意XML是可以接受的,则可以查看Qt文档中的Simple DOM Model Example。
Qt docs中的大多数示例已移植到PyQt,并提供了源代码,可从此处下载。可以在下找到简单DOM模型示例examples/itemviews。
examples/itemviews
编辑 :
我忽略了您正在使用PySide。对于PySide等效停泊的例子可以发现这里,或者在PySide源代码下sources/pyside-examples/examples/itemviews。
sources/pyside-examples/examples/itemviews
更新 :
这是一个使用xml.etree序列化树的简单示例:
import sip sip.setapi('QString', 2) from xml.etree import cElementTree as etree from PyQt4 import QtGui, QtCore class Window(QtGui.QWidget): def __init__(self, xml): QtGui.QWidget.__init__(self) self.tree = QtGui.QTreeWidget(self) self.tree.header().hide() self.importTree(xml) self.button = QtGui.QPushButton('Export', self) self.button.clicked[()].connect(self.exportTree) layout = QtGui.QVBoxLayout(self) layout.addWidget(self.tree) layout.addWidget(self.button) def importTree(self, xml): def build(item, root): for element in root.getchildren(): child = QtGui.QTreeWidgetItem( item, [element.attrib['text']]) child.setFlags( child.flags() | QtCore.Qt.ItemIsEditable) build(child, element) item.setExpanded(True) root = etree.fromstring(xml) build(self.tree.invisibleRootItem(), root) def exportTree(self): def build(item, root): for row in range(item.childCount()): child = item.child(row) element = etree.SubElement( root, 'node', text=child.text(0)) build(child, element) root = etree.Element('root') build(self.tree.invisibleRootItem(), root) from xml.dom import minidom print(minidom.parseString(etree.tostring(root)).toprettyxml()) if __name__ == '__main__': import sys app = QtGui.QApplication(sys.argv) window = Window("""\ <?xml version="1.0" ?> <root> <node text="Child (0)"> <node text="Child (0)"> <node text="Child (0)"/> <node text="Child (1)"/> </node> <node text="Child (1)"> <node text="Child (0)"/> <node text="Child (1)"/> </node> </node> <node text="Child (1)"> <node text="Child (0)"> <node text="Child (0)"/> <node text="Child (1)"/> </node> <node text="Child (1)"> <node text="Child (0)"/> <node text="Child (1)"/> </node> </node> </root> """) window.setGeometry(800, 300, 300, 300) window.show() sys.exit(app.exec_())