PySide 2学習記録(21):QTreeView jsonファイルを読み込む
7274 ワード
Python 2.7またはPython 3.7 PySide 2 Version:5.11.2公式文書:http://doc.qt.io/qtforpython/index.html 参照コード:https://github.com/dridk/QJsonModel/blob/master/qjsonmodel.py
コード
図1
ここでは二つの部分に分けて、前に大きな列がある二つの種類の定義はそれぞれQJson TreeItemとQJJson Modelです。ここではとりあえずこの二つの種類を無視します。QJson Modelという種類の使い方に注目するだけで、qtではjsonデータを載せるモデルが提供されていませんので、ネットで他の人が書いたモデルを見つけました。
コード
# -*- coding:utf-8 -*-
from PySide2 import QtWidgets, QtCore, QtGui
import sys
import json
class QJsonTreeItem(object):
def __init__(self, parent=None):
self._parent = parent
self._key = ""
self._value = ""
self._type = None
self._children = list()
def appendChild(self, item):
self._children.append(item)
def child(self, row):
return self._children[row]
def parent(self):
return self._parent
def childCount(self):
return len(self._children)
def row(self):
return (
self._parent._children.index(self)
if self._parent else 0
)
@property
def key(self):
return self._key
@key.setter
def key(self, key):
self._key = key
@property
def value(self):
return self._value
@value.setter
def value(self, value):
self._value = value
@property
def type(self):
return self._type
@type.setter
def type(self, typ):
self._type = typ
@classmethod
def load(self, value, parent=None, sort=True):
rootItem = QJsonTreeItem(parent)
rootItem.key = "root"
if isinstance(value, dict):
items = (
sorted(value.items())
if sort else value.items()
)
for key, value in items:
child = self.load(value, rootItem)
child.key = key
child.type = type(value)
rootItem.appendChild(child)
elif isinstance(value, list):
for index, value in enumerate(value):
child = self.load(value, rootItem)
child.key = str(index)
child.type = type(value)
rootItem.appendChild(child)
else:
rootItem.value = value
rootItem.type = type(value)
return rootItem
class QJsonModel(QtCore.QAbstractItemModel):
def __init__(self, parent=None):
super(QJsonModel, self).__init__(parent)
self._rootItem = QJsonTreeItem()
self._headers = ("key", "value")
def load(self, document):
"""Load from dictionary
Arguments:
document (dict): JSON-compatible dictionary
"""
assert isinstance(document, (dict, list, tuple)), (
"`document` must be of dict, list or tuple, "
"not %s" % type(document)
)
self.beginResetModel()
self._rootItem = QJsonTreeItem.load(document)
self._rootItem.type = type(document)
self.endResetModel()
return True
def json(self, root=None):
"""Serialise model as JSON-compliant dictionary
Arguments:
root (QJsonTreeItem, optional): Serialise from here
defaults to the the top-level item
Returns:
model as dict
"""
root = root or self._rootItem
return self.genJson(root)
def data(self, index, role):
if not index.isValid():
return None
item = index.internalPointer()
if role == QtCore.Qt.DisplayRole:
if index.column() == 0:
return item.key
if index.column() == 1:
return item.value
elif role == QtCore.Qt.EditRole:
if index.column() == 1:
return item.value
def setData(self, index, value, role):
if role == QtCore.Qt.EditRole:
if index.column() == 1:
item = index.internalPointer()
item.value = str(value)
self.dataChanged.emit(index, index, [QtCore.Qt.EditRole])
return True
return False
def headerData(self, section, orientation, role):
if role != QtCore.Qt.DisplayRole:
return None
if orientation == QtCore.Qt.Horizontal:
return self._headers[section]
def index(self, row, column, parent=QtCore.QModelIndex()):
if not self.hasIndex(row, column, parent):
return QtCore.QModelIndex()
if not parent.isValid():
parentItem = self._rootItem
else:
parentItem = parent.internalPointer()
childItem = parentItem.child(row)
if childItem:
return self.createIndex(row, column, childItem)
else:
return QtCore.QModelIndex()
def parent(self, index):
if not index.isValid():
return QtCore.QModelIndex()
childItem = index.internalPointer()
parentItem = childItem.parent()
if parentItem == self._rootItem:
return QtCore.QModelIndex()
return self.createIndex(parentItem.row(), 0, parentItem)
def rowCount(self, parent=QtCore.QModelIndex()):
if parent.column() > 0:
return 0
if not parent.isValid():
parentItem = self._rootItem
else:
parentItem = parent.internalPointer()
return parentItem.childCount()
def columnCount(self, parent=QtCore.QModelIndex()):
return 2
def flags(self, index):
flags = super(QJsonModel, self).flags(index)
if index.column() == 1:
return QtCore.Qt.ItemIsEditable | flags
else:
return flags
def genJson(self, item):
nchild = item.childCount()
if item.type is dict:
document = {}
for i in range(nchild):
ch = item.child(i)
document[ch.key] = self.genJson(ch)
return document
elif item.type == list:
document = []
for i in range(nchild):
ch = item.child(i)
document.append(self.genJson(ch))
return document
else:
return item.value
def loaddata():
model = QJsonModel()
with open('/Users/wzh/pythonfile/QtFile/population.json', 'r') as f:
data = json.load(f)
model.load(data)
return model
app = QtWidgets.QApplication()
window = QtWidgets.QWidget()
window.setFixedSize(650, 500)
layout = QtWidgets.QHBoxLayout(window)
treeview = QtWidgets.QTreeView(window)
treeview.setModel(loaddata())
# 200
treeview.setColumnWidth(0, 200)
layout.addWidget(treeview)
window.setLayout(layout)
window.show()
sys.exit(app.exec_())
効果図:図1
ここでは二つの部分に分けて、前に大きな列がある二つの種類の定義はそれぞれQJson TreeItemとQJJson Modelです。ここではとりあえずこの二つの種類を無視します。QJson Modelという種類の使い方に注目するだけで、qtではjsonデータを載せるモデルが提供されていませんので、ネットで他の人が書いたモデルを見つけました。
model = QJsonModel()
with open('/Users/wzh/pythonfile/QtFile/population.json', 'r') as f:
data = json.load(f)
model.load(data)
まずmodelを定義して、jsonファイルのファイル記述子を開いて、pythonのjsonモジュールを使ってデータを読み出して、json.load()はファイルの内容の読み取りとアンチプロローグを完了します。dataは辞書タイプです。そしてmodelのload関数を使ってデータをmodelにロードすればいいです。最後にviewにこのmodelを設定すれば表示できます。