我创建了一个简单的QTreeView小部件,并且将QStandardItemModel子类化,但是由于某些原因,当尝试访问它的数据时,我的所有行都没有显示在视图中或打印。这似乎很简单。我必须忽略模型中使它根本无法工作的某些内容。列虽然显示正确。我将打印语句放在def data(...)
中,但它们从未触发,为什么?
import os, sys, datetime
from Qt import QtCore, QtGui, QtWidgets
class ValidationItem(object):
def __init__(self, message, **kwargs):
super(ValidationItem, self).__init__()
self.status = kwargs.get('status', 'info')
self.message = message
class ValidationItemModel(QtGui.QStandardItemModel):
# Constructor
def __init__(self):
super(ValidationItemModel, self).__init__()
self._items = []
self.setHorizontalHeaderLabels(['Status', 'Message'])
# Overrides
def clear(self):
self.beginResetModel()
self._items = []
self.endResetModel()
def rowCount(self, parent=QtCore.QModelIndex()):
if parent.isValid():
return 0
return len(self._items)
def index(self, row, column, parent=QtCore.QModelIndex()):
return self.createIndex(row, column, parent)
def data(self, index, role=QtCore.Qt.DisplayRole):
print 'GETTING DATA'
if not index.isValid():
return None
row = index.row()
col = index.column()
print row, col
item = self.itemByIndex(index.row())
if not item:
return None
print item
if role == QtCore.Qt.UserRole:
return item
return None
# Methods
def itemByIndex(self, index):
print index
if (index < 0 or index >= len(self._items)):
return None
return self._items[index]
def appendItem(self, item):
self.beginInsertRows(QtCore.QModelIndex(), self.rowCount(), self.rowCount())
self._items.append(item)
self.endInsertRows()
print self.rowCount()
class SimpleDialog(QtWidgets.QDialog):
def __init__(self, parent=None):
super(SimpleDialog, self).__init__(parent=parent)
self.resize(500,300)
self.itemModel = ValidationItemModel()
self.itemModel.appendItem(ValidationItem('Hello world! 1', status='warning'))
self.itemModel.appendItem(ValidationItem('Hello world! 2', status='info'))
self.itemModel.appendItem(ValidationItem('Hello world! 3', status='error'))
self.itemModel.appendItem(ValidationItem('Hello world! 4', status='valid'))
self.proxyModel = QtCore.QSortFilterProxyModel()
self.proxyModel.setSourceModel(self.itemModel)
self.treeView = QtWidgets.QTreeView()
self.treeView.setModel(self.proxyModel)
self.layout = QtWidgets.QVBoxLayout()
self.layout.addWidget(self.treeView)
self.setLayout(self.layout)
def main():
app = QtWidgets.QApplication(sys.argv)
ex = SimpleDialog()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
已更新
下面是我正在工作的更新代码。发布此代码的原因,如果是因为用户建议我在下面自定义QStandardItem而不是模型。我希望他可以用我的代码进行演示,以便我可以更好地了解如何执行此操作。需要注意的主要事情是用户可以双击一个项目,它将执行通过UserRole访问它的每个项目的run
功能。
import os, sys, datetime
from Qt import QtCore, QtGui, QtWidgets
class ValidationItem(object):
def __init__(self, message, **kwargs):
super(ValidationItem, self).__init__()
self.status = kwargs.get('status', 'info')
self.message = message
def run(self):
print 'STUBBED IN METHOD', self.status, self.message
class ValidationItemURL(ValidationItem):
def __init__(self, message, **kwargs):
super(ValidationItem, self).__init__()
self.status = kwargs.get('status', 'info')
self.message = message
def run(self):
os.startfile('https://stackoverflow.com/')
class ValidationItemModel(QtCore.QAbstractTableModel):
VALIDATION_STATUSES = {
'error': QtGui.QColor(220,70,55),
'warning': QtGui.QColor(240,180,10),
'valid': QtGui.QColor(10,170,70)
}
# Constructor
def __init__(self):
super(ValidationItemModel, self).__init__()
self._items = []
self._headers = ['Status', 'Message']
# Overrides
def headerData(self, section, orientation, role):
if role == QtCore.Qt.DisplayRole:
if orientation == QtCore.Qt.Horizontal:
return self._headers[section]
def flags(self, index):
return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
def clear(self):
self.beginResetModel()
self._items = []
self.endResetModel()
def rowCount(self, parent=QtCore.QModelIndex()):
if parent.isValid():
return 0
return len(self._items)
def columnCount(self, parent):
return len(self._headers)
def data(self, index, role=QtCore.Qt.DisplayRole):
if not index.isValid():
return None
item = self.itemByIndex(index.row())
if not item:
return None
row = index.row()
column = index.column()
if role == QtCore.Qt.DisplayRole:
if column == 0:
return item.status.title()
elif column == 1:
return item.message
elif role == QtCore.Qt.ToolTipRole:
if column == 0:
return item.status.title()
elif column == 1:
return item.message
elif role == QtCore.Qt.ForegroundRole:
if column == 0:
if item.status in self.VALIDATION_STATUSES:
return self.VALIDATION_STATUSES[item.status]
if role == QtCore.Qt.UserRole:
return item
return None
# Methods
def itemByIndex(self, index):
if (index < 0 or index >= len(self._items)):
return None
return self._items[index]
def appendItem(self, item):
if isinstance(item, ValidationItem):
self.beginInsertRows(QtCore.QModelIndex(), self.rowCount(), self.rowCount())
self._items.append(item)
self.endInsertRows()
class SimpleDialog(QtWidgets.QDialog):
def __init__(self, parent=None):
super(SimpleDialog, self).__init__(parent=parent)
self.resize(500,300)
self.itemModel = ValidationItemModel()
self.itemModel.appendItem(ValidationItem('Hello world! 1', status='warning'))
self.itemModel.appendItem(ValidationItem('Hello world! 2', status='info'))
self.itemModel.appendItem(ValidationItem('Hello world! 3', status='error'))
self.itemModel.appendItem(ValidationItemURL('stackoverflow (double-click to visit)', status='valid'))
self.proxyModel = QtCore.QSortFilterProxyModel()
self.proxyModel.setSourceModel(self.itemModel)
self.treeView = QtWidgets.QTreeView()
self.treeView.setModel(self.proxyModel)
self.layout = QtWidgets.QVBoxLayout()
self.layout.addWidget(self.treeView)
self.setLayout(self.layout)
# Signals
self.treeView.doubleClicked.connect(self.slotDoubleClickedItem)
# Slots
def slotDoubleClickedItem(self, index):
if index.isValid():
item = index.data(role=QtCore.Qt.UserRole)
if item:
item.run()
def main():
app = QtWidgets.QApplication(sys.argv)
ex = SimpleDialog()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()