如何保存PySide树视图模型结构 [英] How to save PySide tree view model structure

查看:38
本文介绍了如何保存PySide树视图模型结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是其他 SO 问题的链接带有自定义项目的 QTreeView,其中 QTreeView 示例在哪里.

Here is the link on other SO question QTreeView with custom items where is QTreeView example.

请,谁能在这个例子中解释我,如何从树视图中保存树结构.

Please, can anyone explain me at this example, how to save tree structure from treeview.

  1. 是否可以从 QAbstractItemModel 类中提取标签名称和可以再次加载的结构?

  1. Is the QAbstractItemModel class from which I can extract label names, and structure which I could load again?

如果是这样,我如何访问节点?除了索引还有其他方法吗?

If so, how could I access to nodes? Any other way except index?

编辑(来自链接):

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()

推荐答案

你的问题很不清楚,因为你没有说你想要以什么形式保存树结构.

Your question is quite unclear, because you don't say what form you want the tree structure saved in.

假设您并不真正关心,并且 XML 是可以接受的,您可以查看 Qt 文档中的简单 DOM 模型示例.

Assuming that you don't really care, and that XML would be acceptable, you could take a look at the Simple DOM Model Example from the Qt docs.

Qt 文档中的大部分示例已移植到 PyQt,并提供源代码,可从 这里.简单 DOM 模型示例可以在 examples/itemviews 下找到.

Most of the examples from the Qt docs have been ported to PyQt, and are provided with the source code, which can be downloaded from here. The Simple DOM Model example can be found under examples/itemviews.

编辑:

我忽略了您正在使用 PySide.可以在此处或<sources/pyside-examples/examples/itemviews 下的 href="https://qt-project.org/wiki/Get-PySide" rel="noreferrer">PySide 源代码.

I overlooked that you were using PySide. The equivalent ported examples for PySide can be found here, or in the PySide source code under sources/pyside-examples/examples/itemviews.

更新:

这是一个简单的例子,它使用 xml.etree 序列化树:

Here's a simple example which uses xml.etree to serialize the tree:

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_())

这篇关于如何保存PySide树视图模型结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆