QListView с CustomWIdget с использованием QStyledItemDelegate

Я пытаюсь создать QListView с QStyledItemDelegate, чтобы показать данные более организованным способом.

Я просмотрел этот сайт и все это на С++, и я понятия не имею об этом, догадываясь по синтаксису и вызовам, которые использовались в посте, я пытался добиться этого, но мне не повезло. Может кто-нибудь, пожалуйста, помогите мне с этим?

import sys, os

from PyQt4 import QtGui, QtCore


class ListView(QtGui.QListView):
    def __init__(self, parent=None):
        super(ListView, self).__init__(parent)

        self._model = None
        self._data = [
                        [
                        'Header: King Arthur',
                        'Project: TBN',
                        'Asset: arthur',
                        'Task name: Design doc',
                        'Start Date: Today',
                        'End Date: Next Monday'
                        ]
                    ]
        self.set_model()
        item_delegate = ItemDelegate()
        self.setItemDelegate(item_delegate)
        self.openPersistentEditor(self._model.createIndex(0, 0))

    def set_model(self):
        self._model = ListModel(self._data, parent=self)
        self.setModel(self._model)


class ListModel(QtCore.QAbstractItemModel):
    def __init__(self, data=[], parent=None):
        super(ListModel, self).__init__(parent)
        self._data = data

    def rowCount(self, *arg):
        return 1 

    def columnCount(self, *arg):
        return len(self._data)

    def data(self, index, role):
        row = index.row()
        column = index.column()

        if role == QtCore.Qt.DisplayRole:
            return QtCore.QVariant(' | '.join(self._data[column]))

        return QtCore.QVariant()

    def index(self, row, column, parent):
        return self.createIndex(row, column)

    def parent(self, index):
        item = index.internalPointer()
        if item:
            return item.getParent()
        else:
            item = self.createIndex(index.row(), index.column()).internalPointer()
            if item:
                return item.getParent()

        return QtCore.QModelIndex()

class ItemDelegate(QtGui.QStyledItemDelegate):
    def createEditor(self, parent, option, index):
        item_data = str(index.data().toString())
        editor = Widget(item_data.split('|'), parent=parent)
        return editor

    def updateEditorGeometry(self, editor, option, index):
        editor.setGeometry(option.rect) 

class Widget(QtGui.QWidget):
    def __init__(self, widget_data=[], parent=None):
        super(Widget, self).__init__(parent)

        vbox = QtGui.QVBoxLayout(self)
        key_font = QtGui.QFont()
        key_font.setWeight(QtGui.QFont.Bold)
        val_font = QtGui.QFont()
        val_font.setWeight(QtGui.QFont.Normal)

        for each_data in widget_data:
            hbox = QtGui.QHBoxLayout()
            key, value = each_data.split(':')
            key_text = QtGui.QLabel(self)
            val_text = QtGui.QLabel(self)

            key_text.setToolTip('Key: %s' % key)
            val_text.setToolTip('Value: %s' % value)

            key_text.setText(key)
            val_text.setText(value)

            key_text.setFont(key_font)
            val_text.setFont(val_font)

            hbox.addWidget(key_text)
            hbox.addWidget(val_text)
            # vbox.addLayout(hbox)


if __name__ == '__main__':
    qapp = QtGui.QApplication([])
    app = ListView()
    app.show()
    sys.exit(qapp.exec_())

person Mahendra    schedule 20.03.2016    source источник
comment
Ваш вопрос очень расплывчатый. Чего вы пытаетесь достичь и какова точная проблема, с которой вы сталкиваетесь? Также я не вижу сходства между вашим кодом и кодом C++ блога, на который вы ссылаетесь. В блоге объясняется, как использовать делегат для переноса слов в ячейках. Это то, что вы пытаетесь сделать? В этом случае вам, вероятно, следует также реализовать методы sizeHint и paint класса ListViewDelegate.   -  person titusjan    schedule 21.03.2016
comment
Спасибо за ответ titusjan. Да, вместо переноса текста я хочу показать CustomWidget, который показывает данные. Прямо сейчас виджет не отображается должным образом в QListView.   -  person Mahendra    schedule 21.03.2016


Ответы (2)


Если у вас нет веских причин для использования шаблона View/Model, в большинстве случаев будет проще использовать шаблон Widget/Item — QListWidget и QListWidgetItem.

QItemDelegate и QStyledItemDelegate предназначены для создания подклассов. Затем вы определяете методы, отвечающие за обработку событий, изменение размера и отрисовку представлений/виджетов.

class MyWidget(QtGui.QWidget):

    def __init__(self, parent):
        super(MyWidget, self).__init__(parent)
        self.listwidget = QtGui.QListWidget(self)
        self.delegate = MyDelegate(self, self.listwidget)
        self.listwidget.setItemDelegate(self.delegate)

        datas = [
            {'Header': 'Blah', 'Project': 'TBN'},
            {'Header': 'Other', 'Project': 'Something'},
        ]
        for data in datas:
            MyItem(self.listwidget, data)       


class MyItem(QtGui.QListWidgetItem):

    def __init__(self, parent, data):
        super(MyItem, self).__init__(parent)
        self._data = data


class MyDelegate(QtGui.QStyledItemDelegate):

    def __init__(self, parent, listwidget):
        super(MyDelegate, self).__init__(parent)
        self.listwidget = listwidget

    def sizeHint(self, option, index):
         if index:
             item = self.listwidget.itemFromIndex(index)
             print item._data 
             # Do fontmetrics stuff from C++ article you linked
             # using the text in the data dictionary.

    def paint(self, painter, option, index):
        # same thing, get the item using the index
        # get the data from the item
        # paint the data however you want.          
person Brendan Abel    schedule 21.03.2016
comment
Спасибо за образец, Бренден. В моем коде у меня была проблема, когда виджеты складывались в верхнем углу, я попытался реализовать класс делегата метода {paint}, и это было исправлено. - person Mahendra; 22.03.2016
comment
Вам нужно использовать qlayouts для размещения ваших виджетов - person Brendan Abel; 22.03.2016
comment
Уже использую его в классе виджетов выше, я что-то упускаю или делаю неправильно? - person Mahendra; 22.03.2016

class ItemDelegate(QtGui.QStyledItemDelegate):
    def createEditor(self, parent, option, index):
        item_data = str(index.data().toString())
        editor = Widget(item_data.split('|'), parent=parent)
        return editor

    def updateEditorGeometry(self, editor, option, index):
        editor.setGeometry(option.rect) 
    def paint(self, painter, option, index):
        painter.save()
        index.model().setData(index, option.rect.width(), Qt.UserRole+1)

исправил эту проблему

person Mahendra    schedule 22.03.2016