我从previous post的答案开始,但它似乎没有起作用。所有行都呈现相同的颜色。
我创建了一个主窗口类
import sys
from PySide import QtCore, QtGui
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.settingsTree = SettingsTree()
self.setCentralWidget(self.settingsTree)
self.locationDialog = None
# self.autoRefreshAct.setChecked(True)
# self.fallbacksAct.setChecked(True)
self.setWindowTitle("Test")
self.resize(500, 600)
self.setTreeDataObject(ItemManifest())
self.settingsTree.setItemDelegate(SelectionColorDelegate(self.settingsTree))
def setTreeDataObject(self, treeData):
self.settingsTree.setTreeDataObject(treeData)
# self.refreshAct.setEnabled(True)
# self.autoRefreshAct.setEnabled(True)
ItemManifest用于保存特定于列表项的数据(不确定这是Qt的做事方式)
class ItemManifest(QtCore.QObject):
def __init__(self, parent=None):
super(ItemManifest, self).__init__(parent)
self.myList = [{'name': 'a', 'vid':'1', 'pid': '1'},
{'name': 'b', 'vid':'2', 'pid': '1'},
{'name': 'c', 'vid':'3', 'pid': '1'}]
这是我的实际树小部件,有三列:
class SettingsTree(QtGui.QTreeWidget):
def __init__(self, parent=None):
super(SettingsTree, self).__init__(parent)
self.setHeaderLabels(("Name", "vid", "pid"))
self.header().setResizeMode(0, QtGui.QHeaderView.Stretch)
self.header().setResizeMode(2, QtGui.QHeaderView.Stretch)
self.refreshTimer = QtCore.QTimer()
self.refreshTimer.setInterval(2000)
self.autoRefresh = False
self.groupIcon = QtGui.QIcon()
self.groupIcon.addPixmap(self.style().standardPixmap(QtGui.QStyle.SP_DirClosedIcon),
QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.groupIcon.addPixmap(self.style().standardPixmap(QtGui.QStyle.SP_DirOpenIcon),
QtGui.QIcon.Normal, QtGui.QIcon.On)
self.keyIcon = QtGui.QIcon()
self.keyIcon.addPixmap(self.style().standardPixmap(QtGui.QStyle.SP_FileIcon))
self.refreshTimer.timeout.connect(self.refresh)
def setTreeDataObject(self, treeData):
self.treeData = treeData
self.clear()
if self.treeData is not None:
self.treeData.setParent(self)
self.refresh()
if self.autoRefresh:
self.refreshTimer.start()
else:
self.refreshTimer.stop()
def sizeHint(self):
return QtCore.QSize(800, 600)
def setAutoRefresh(self, autoRefresh):
self.autoRefresh = autoRefresh
if self.treeData is not None:
if self.autoRefresh:
self.refresh()
self.refreshTimer.start()
else:
self.refreshTimer.stop()
def refresh(self):
if self.treeData is None:
return
# The signal might not be connected.
# try:
# self.itemChanged.disconnect(self.updateSetting)
# except:
# pass
self.updateChildItems(None)
# self.itemChanged.connect(self.updateSetting)
def event(self, event):
if event.type() == QtCore.QEvent.WindowActivate:
if self.isActiveWindow() and self.autoRefresh:
self.refresh()
return super(SettingsTree, self).event(event)
'''on change to settings update tree'''
def updateChildItems(self, parent):
dividerIndex = 0
for printer in self.treeData.myList:
childIndex = self.findChild(parent, printer['name'], 0)
if childIndex == -1 or childIndex >= dividerIndex:
if childIndex != -1:
child = self.childAt(parent, childIndex)
for i in range(child.childCount()):
self.deleteItem(child, i)
self.moveItemForward(parent, childIndex, dividerIndex)
else:
child = self.createItem(printer['name'], parent, dividerIndex)
child.setIcon(0, self.keyIcon)
dividerIndex += 1
else:
child = self.childAt(parent, childIndex)
child.setText(1, printer['vid'])
child.setText(2, printer['pid'])
def createItem(self, text, parent, index):
after = None
if index != 0:
after = self.childAt(parent, index - 1)
if parent is not None:
item = QtGui.QTreeWidgetItem(parent, after)
else:
item = QtGui.QTreeWidgetItem(self, after)
item.setText(0, text)
item.setFlags(item.flags() | QtCore.Qt.ItemIsEditable)
return item
def deleteItem(self, parent, index):
if parent is not None:
item = parent.takeChild(index)
else:
item = self.takeTopLevelItem(index)
del item
def childAt(self, parent, index):
if parent is not None:
return parent.child(index)
else:
return self.topLevelItem(index)
def childCount(self, parent):
if parent is not None:
return parent.childCount()
else:
return self.topLevelItemCount()
def findChild(self, parent, text, startIndex):
for i in range(self.childCount(parent)):
if self.childAt(parent, i).text(0) == text:
return i
return -1
def moveItemForward(self, parent, oldIndex, newIndex):
for int in range(oldIndex - newIndex):
self.deleteItem(parent, newIndex)
创建一个颜色委托,用于设置文本“a”为绿色
的行的背景颜色class SelectionColorDelegate(QtGui.QStyledItemDelegate):
def __init__(self, parent):
super(SelectionColorDelegate, self).__init__(parent)
def initStyleOption(self, option, index):
# let the base class initStyleOption fill option with the default values
super(SelectionColorDelegate,self).initStyleOption(option, index)
# override what you need to change in option
if index.data() == 'a':
backColor = QtGui.QColor("green")
option.palette.setColor(QtGui.QPalette.Base, backColor)
option.backgroundBrush = backColor
让它发挥作用:
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
mainWin = MainWindow()
mainWin.show()
sys.exit(app.exec_())
我设置背景颜色的尝试似乎都没有效果。
答案 0 :(得分:4)
在进一步学习Qt之后,我重构了代码以使用模型/视图关系。该模型继承自QtCore.QAbstractItemModel,并按如下方式实现数据方法:
class MyTreeModel(QtCore.QAbstractItemModel):
def data(self, index, role):
if not index.isValid():
return None
item = index.internalPointer()
if role == QtCore.Qt.BackgroundRole:
if item.status.status == 'Not installed':
return QtGui.QBrush(QtCore.Qt.lightGray)
if item.status.head_test_failed:
return QtGui.QBrush(QtCore.Qt.red)
if item.status.status == 'failure':
return QtGui.QBrush(QtCore.Qt.red)
if item.status.status == 'running':
return QtGui.QBrush(QtCore.Qt.green)
return QtGui.QBrush(QtCore.Qt.transparent)
if role != QtCore.Qt.DisplayRole:
return None
return item.data(index.column())
这样我就可以使用标准的TreeView(或任何其他视图)。 role == QtCore.Qt.BackgroundRole
告诉模型这是格式化请求。