我看了很多在线教程/视频试图让QTreeView工作。我了解基本原理并使示例工作。但是,现在我想对正常的数据更改机制进行更改。
通常,示例显示通过GUI更改数据。相反,我需要通过一个单独的运行线程来更改数据(即TreeView将是只读的)。在应用程序中,线程处理定期检索数据,我想相应地更新TreeView。
以下是我到目前为止尝试过的一些示例代码。 TreeView应显示第一列中的树结构,并显示第二列中每个树项的值。数据线程更新树节点值。我想看到的是价值自身增加。相反,当我鼠标打开/关闭项目时,我只看到更新的值。这告诉我线程成功更新了值,但看起来TreeView没有响应dataChanged信号。
我似乎很接近,但我看不出什么是不对的......想法?
import sys
import threading
import time
from PyQt4 import QtGui, QtCore
class Node(object):
def __init__(self, name, parent=None):
self._name = name
self._value = 0
self._children = []
self._parent = parent
if parent is not None:
parent.addChild(self)
def addChild(self, child):
self._children.append(child)
def name(self):
return self._name
def value(self):
return self._value
def setValue(self, value):
self._value = value
def child(self, row):
return self._children[row]
def childCount(self):
return len(self._children)
def children(self):
return self._children
def parent(self):
return self._parent
def row(self):
if self._parent is not None:
return self._parent._children.index(self)
class Model(QtCore.QAbstractItemModel):
def __init__(self, parent=None):
super(Model, self).__init__(parent)
self._root = None
self.setupData()
def setupData(self):
rootNode = Node('Root')
childNode0 = Node('A', rootNode)
childNode1 = Node('B', rootNode)
childNode2 = Node('1', childNode0)
childNode3 = Node('2', childNode0)
childNode4 = Node('1', childNode1)
childNode5 = Node('2', childNode1)
childNode6 = Node('a', childNode3)
childNode7 = Node('b', childNode3)
childNode8 = Node('c', childNode3)
childNode9 = Node('d', childNode4)
childNode10 = Node('e', childNode4)
childNode11 = Node('f', childNode4)
self._root = rootNode
def rowCount(self, parent=None):
if not parent.isValid():
parentNode = self._root
else:
parentNode = parent.internalPointer()
return parentNode.childCount()
def columnCount(self, parent=None):
return 2
def data(self, index, role):
if not index.isValid():
return None
node = index.internalPointer()
if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole:
if index.column() == 0:
return node.name()
if index.column() == 1:
return node.value()
return None
def headerData(self, section, orientation, role):
if role == QtCore.Qt.DisplayRole:
if section == 0:
return 'Item'
if section == 1:
return 'Value'
return None
def index(self, row, column, parent):
parentNode = self.getNode(parent)
childItem = parentNode.child(row)
if childItem:
return self.createIndex(row, column, childItem)
else:
return QtCore.QModelIndex()
def getNode(self, index):
if index.isValid():
node = index.internalPointer()
if node:
return node
return self._root
def parent(self, index):
node = self.getNode(index)
parentNode = node.parent()
if parentNode == self._root:
return QtCore.QModelIndex()
return self.createIndex(parentNode.row(), 0, parentNode)
def changeData(self, name, value):
# find the 'name' node and have setData make the change
index = self.searchModel(name)
self.setData(index, value)
def setData(self, index, value, role=QtCore.Qt.EditRole):
if index.isValid():
if role == QtCore.Qt.EditRole:
node = index.internalPointer()
node.setValue(value)
# signal the views that data has changed
self.dataChanged.emit(index, index)
return True
return False
def searchModel(self, name):
def searchNode(node):
for child in node.children():
if child.name().endswith(name):
index = self.createIndex(child.row(), 0, child)
return index
if child.childCount() > 0:
result = searchNode(child)
if result:
return result
return searchNode(self._root)
class DataThread(threading.Thread):
def __init__(self, model):
threading.Thread.__init__(self)
self.__model = model
self.__runflag = False
def run(self):
print 'Running'
value = 0
self.__runflag = True
while self.__runflag:
# sample, change a single value
self.__model.changeData('c', value)
value += 1
time.sleep(1)
print 'Terminated'
def stop(self):
print 'Stopping'
self.__runflag = False
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
model = Model()
view = QtGui.QTreeView()
view.setModel(model)
view.expandAll()
view.show()
data_thread = DataThread(model)
data_thread.start()
app.exec_()
data_thread.stop()
sys.exit()
答案 0 :(得分:1)
传递给dataChanged信号的模型索引的列值为0.但是,您要更新的列是1.
在searchNode
中,更改构造索引的行:
index = self.createIndex(child.row(), 1, child)
它应该工作。