QTreeView не отображает элементы - PullRequest
0 голосов
/ 04 октября 2019

Я создал простой виджет QTreeView, и я создаю подкласс QStandardItemModel, но по какой-то причине ни одна из моих строк не отображается в представлении или печати при попытке доступа к его данным. Это кажется очень простой вещью. Я, должно быть, упускаю из виду в моей модели что-то, что вообще не работает. Хотя столбцы отображаются правильно. Я помещаю операторы печати в def data(...), но они никогда не срабатывают, почему?

enter image description here

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 вместо модели. Я надеюсь, что он сможет продемонстрировать это с помощью моего кода, чтобы я мог лучше понять, как это сделать. Главное, на что следует обратить внимание: пользователи могут дважды щелкнуть по элементу, и он будет выполнять функцию run каждого элемента, обращающегося к нему через пользовательскую роль.

enter image description here

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()
...