可编辑树状视图 - 更改编辑字段的类型

时间:2017-04-19 09:36:29

标签: qt view pyqt pyqt5

我有这样的字典:

{"key1": 1, "key2": 0, "key3": {"key": 1}, "dupa": None}

我想将其编辑为树视图,但我无法更改key1来存储字符串。

我看到了editable model view example。并编辑它以显示我的字典 这是一个例子:

My tree view

查看读取的“区域”,因为您可以预期无法在此字段中插入字符串。

所以我的问题是:
  1. 我应该覆盖巫婆类或功能以允许显示的控制编辑项目(我想添加允许更改类型的控件并删除整个项目或添加新项目)?换句话说:我怎样才能将字符串放入此字段?
  2. 我在哪里可以找到这个函数/类的原始定义?
  3. 我使用了qt标记,因为您可以在C ++示例中回答我的问题,我可以将其翻译为python。

    我编辑的代码:(准备复制并运行)但我认为没有必要查看它,回答我的问题。

    from PyQt5.QtCore import (QAbstractItemModel, QFile, QIODevice,
                              QItemSelectionModel, QModelIndex, Qt, QAbstractItemModel, QObject)
    from PyQt5.QtWidgets import QApplication, QMainWindow, QHBoxLayout
    from PyQt5 import QtCore, QtGui, QtWidgets
    
    
    class TreeItem(object):
        def __init__(self, data, parent=None):
            self.parentItem = parent
            self.itemData = data  # it's also []
            self.childItems = []
    
        def child(self, row):
            return self.childItems[row]
    
        def childCount(self):
            return len(self.childItems)
    
        def childNumber(self):
            if self.parentItem is not None:
                return self.parentItem.childItems.index(self)
            return 0
    
        def columnCount(self):
            return len(self.itemData)
    
        def data(self, column):
            return self.itemData[column]
    
        def insertChildren(self, position, count, columns):
            if position < 0 or position > len(self.childItems):
                return False
    
            for row in range(count):
                data = [None for v in range(columns)]
                item = TreeItem(data, self)
                self.childItems.insert(position, item)
    
            return True
    
        def appendChild_by_item(self, item):
            item.parentItem = self
            self.childItems.append(item)
    
        def appendChild_by_data(self, data):
            self.childItems.append(TreeItem(data, self))
    
        def insertColumns(self, position, columns):
            if position < 0 or position > len(self.itemData):
                return False
    
            for column in range(columns):
                self.itemData.insert(position, None)
    
            for child in self.childItems:
                child.insertColumns(position, columns)
    
            return True
    
        def parent(self):
            return self.parentItem
    
        def removeChildren(self, position, count):
            if position < 0 or position + count > len(self.childItems):
                return False
    
            for row in range(count):
                self.childItems.pop(position)
    
            return True
    
        def removeColumns(self, position, columns):
            if position < 0 or position + columns > len(self.itemData):
                return False
    
            for column in range(columns):
                self.itemData.pop(position)
    
            for child in self.childItems:
                child.removeColumns(position, columns)
    
            return True
    
        def setData(self, column, value):
            if column < 0 or column >= len(self.itemData):
                return False
    
            self.itemData[column] = value
    
            return True
    
    
    class TreeModel(QAbstractItemModel):
        def __init__(self, headers, data, parent=None):
            super(TreeModel, self).__init__(parent)
    
            rootData = [header for header in headers]
            self.rootItem = TreeItem(rootData)
            self.setupModelData(data, self.rootItem)
    
            print(self.rootItem.childCount())
    
        def columnCount(self, parent=QModelIndex()):
            return self.rootItem.columnCount()
    
        def data(self, index, role):
            if not index.isValid():
                return None
    
            if role != Qt.DisplayRole and role != Qt.EditRole:
                return None
    
            item = self.getItem(index)
            return item.data(index.column())
    
        def flags(self, index):
            if not index.isValid():
                return 0
    
            return Qt.ItemIsEditable | Qt.ItemIsEnabled | Qt.ItemIsSelectable
    
        def getItem(self, index):
            if index.isValid():
                item = index.internalPointer()
                if item:
                    return item
    
            return self.rootItem
    
        def headerData(self, section, orientation, role=Qt.DisplayRole):
            if orientation == Qt.Horizontal and role == Qt.DisplayRole:
                return self.rootItem.data(section)
    
            return None
    
        def index(self, row, column, parent=QModelIndex()):
            if parent.isValid() and parent.column() != 0:
                return QModelIndex()
    
            parentItem = self.getItem(parent)
            childItem = parentItem.child(row)
            if childItem:
                return self.createIndex(row, column, childItem)
            else:
                return QModelIndex()
    
        def insertColumns(self, position, columns, parent=QModelIndex()):
            self.beginInsertColumns(parent, position, position + columns - 1)
            success = self.rootItem.insertColumns(position, columns)
            self.endInsertColumns()
    
            return success
    
        def insertRows(self, position, rows, parent=QModelIndex()):
            parentItem = self.getItem(parent)
            self.beginInsertRows(parent, position, position + rows - 1)
            success = parentItem.insertChildren(position, rows,
                                                self.rootItem.columnCount())
            self.endInsertRows()
    
            return success
    
        def parent(self, index):
            if not index.isValid():
                return QModelIndex()
    
            childItem = self.getItem(index)
            parentItem = childItem.parent()
    
            if parentItem == self.rootItem:
                return QModelIndex()
    
            return self.createIndex(parentItem.childNumber(), 0, parentItem)
    
        def removeColumns(self, position, columns, parent=QModelIndex()):
            self.beginRemoveColumns(parent, position, position + columns - 1)
            success = self.rootItem.removeColumns(position, columns)
            self.endRemoveColumns()
    
            if self.rootItem.columnCount() == 0:
                self.removeRows(0, self.rowCount())
    
            return success
    
        def removeRows(self, position, rows, parent=QModelIndex()):
            parentItem = self.getItem(parent)
    
            self.beginRemoveRows(parent, position, position + rows - 1)
            success = parentItem.removeChildren(position, rows)
            self.endRemoveRows()
    
            return success
    
        def rowCount(self, parent=QModelIndex()):
            parentItem = self.getItem(parent)
    
            return parentItem.childCount()
    
        def setData(self, index, value, role=Qt.EditRole):
            if role != Qt.EditRole:
                return False
    
            item = self.getItem(index)
            result = item.setData(index.column(), value)
    
            if result:
                self.dataChanged.emit(index, index)
    
            return result
    
        def setHeaderData(self, section, orientation, value, role=Qt.EditRole):
            if role != Qt.EditRole or orientation != Qt.Horizontal:
                return False
    
            result = self.rootItem.setData(section, value)
            if result:
                self.headerDataChanged.emit(orientation, section, section)
    
            return result
    
        def setupModelData(self, nested_dict, parent):
            print(nested_dict)
            for k, v in nested_dict.items():
                if isinstance(v, dict):
                    parent.appendChild_by_data([k, None])
                    self.setupModelData(v, parent.child(parent.childCount() - 1))
                else:
                    parent.appendChild_by_data([k, v])
    
    
    class MainWindow(QMainWindow):
        """docstring for MainWindow"""
    
        def __init__(self, data, parent=None):
            super(MainWindow, self).__init__(parent=None)
    
            headersLabels = ("Key", "value")
            self.orginal_data = data
            print(data)
            self.m_model = TreeModel(headersLabels, data)
    
            self.container = QtWidgets.QWidget()
            self.m_view = QtWidgets.QTreeView()
            self.m_view.setModel(self.m_model)
    
            self.testButton = QtWidgets.QPushButton("Test")
            self.testButton.clicked.connect(self.testAction)
    
            self.buttonLayout = QHBoxLayout()
            self.buttonLayout.addWidget(self.testButton)
    
            self.container_layout = QtWidgets.QVBoxLayout()
            self.container_layout.addWidget(self.m_view)
            self.container_layout.addLayout(self.buttonLayout)
    
            self.container.setLayout(self.container_layout)
            self.setCentralWidget(self.container)
    
        def testAction(self):
    
            selceteds = self.m_view.selectedIndexes()
            print(selceteds)
            for i in selceteds:
                item = self.m_model.getItem(i)
                print(item.data(i.column()))
    
    
    if __name__ == '__main__':
        import sys
    
        _d = {"key1": 1, "key2": 0, "key3": {"key": 1}, "dupa": None}
    
        app = QApplication(sys.argv)
        window = MainWindow(_d)
        window.show()
        sys.exit(app.exec_())
    

    我希望我的英语足够了解

1 个答案:

答案 0 :(得分:2)

如果您不喜欢内置代理提供的编辑器,则需要实现自定义delegate来修改模型项。

在您的情况下,您需要创建QStyledItemDelegate的子类并重新实现方法createEditor(很可能您希望从中返回QLineEdit),{{ 3}}(设置从数字转换为编辑器的字符串),setEditorData(设置从字符串转换回模型的数字)。然后,您需要将代理设置为视图。

您可能希望查看setModelData示例,但您的用例似乎更简单:您不需要重新实现项目绘制。