Изменение размера делегата и взаимодействие с ним - PullRequest
0 голосов
/ 29 апреля 2019

Я создаю пользовательский элемент делегата для ленты новостей, которую пытаюсь создать в pyside.Я не совсем уверен, как заставить textEdit автоматически настраивать его размер, чтобы он соответствовал содержанию текста, который он переносит, и, во-вторых, поддерживать функцию взаимодействия с текстом, где пользователи могут щелкать и выделять текст?

Это то, что яСейчас я получаю, и вы можете видеть, что текстовые поля отображаются поверх и имеют неправильный размер по вертикали:

enter image description here

import os, sys
from Qt import QtWidgets, QtCore, QtGui


class NewsItem(object):
    def __init__(self, **kwargs):
        super(NewsItem, self).__init__()
        self.title = kwargs.get('title', '')
        self.date = kwargs.get('date', '')
        self.content = kwargs.get('content', '')


class NewsItemDelegate(QtWidgets.QItemDelegate):

    def __init__(self, parent=None):
        super(NewsItemDelegate, self).__init__(parent)


    def paint(self, painter, option, index):
        # rect = option.rect.adjusted(1, 1, -1, -1)
        # painter.fillRect(rect, QtGui.QColor(20,40,170,50))
        # QtWidgets.QItemDelegate.paint(self, painter, option, index)

        # get data from userrole
        data = index.data(role=QtCore.Qt.UserRole)

        # Main Widget
        title = QtWidgets.QLabel(data.title)
        content = QtWidgets.QTextEdit(data.content)
        content.setFixedHeight(content.sizeHint().height())

        widget = QtWidgets.QWidget()
        layout = QtWidgets.QGridLayout(widget)
        layout.addWidget(title, 0, 0)
        layout.addWidget(content, 1, 0)
        widget.setGeometry(option.rect)

        widget.render(painter, option.rect.topLeft())

        # painter.save()
        # painter.restore()


    def sizeHint(self, option, index):
        return QtCore.QSize(100, 50)
        return QtWidgets.QItemDelegate.sizeHint(self, option, index)


class NewsModel(QtGui.QStandardItemModel):

    def __init__(self, *args, **kwargs):
        QtGui.QStandardItemModel.__init__(self, *args, **kwargs)


class NewsListView(QtWidgets.QListView):
    def __init__(self, parent=None):
        super(NewsListView, self).__init__(parent)

        self.setModel(NewsModel(self))
        self.setItemDelegate(NewsItemDelegate(self))
        self.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
        self.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)


    def setNewsItems(self, lst):
        self.model().clear()
        for x in lst:
            item = QtGui.QStandardItem()
            # item.setData(x.title, role=QtCore.Qt.DisplayRole)
            item.setData(x, role=QtCore.Qt.UserRole)
            self.model().appendRow(item)


class MainWindow(QtWidgets.QMainWindow):

    def __init__(self):
        super(MainWindow, self).__init__()
        self.resize(350, 500)

        # Controls
        self.uiListView = NewsListView()
        self.setCentralWidget(self.uiListView)


    def unitTest(self):
        self.uiListView.setNewsItems([
            NewsItem(title='Big Update', date='Today', content='Something goes here...'),
            NewsItem(title='Smaller Update', date='Yesterday', content='Something goes here which should support word wrap'),
            NewsItem(title='Another Update', date='Last Year', content='Something goes here...'),
            NewsItem(title='Old Update', date='Unknown', content='Something goes here...'),
        ])


def main():
    app = QtWidgets.QApplication(sys.argv)
    ex = MainWindow()
    ex.unitTest()
    ex.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

1 Ответ

0 голосов
/ 01 мая 2019

В этом типе случаев необходимо создать виджет в качестве редактора, и для этого вы должны сделать в методе рисования вызов openPersistentEditor (). Методы createEditor (), setEditorData () и setModelData () также должны быть перезаписаны.

# ...
from functools import partial
# ...
class EditorWidget(QtWidgets.QWidget):
    editingFinished = QtCore.Signal()

    def __init__(self, data=None, parent=None):
        super(EditorWidget, self).__init__(parent)
        self.title_label = QtWidgets.QLabel()
        self.content_textedit = QtWidgets.QTextEdit()
        self.content_textedit.textChanged.connect(self.editingFinished)
        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(self.title_label)
        lay.addWidget(self.content_textedit)
        if data is not None:
            self.data = data

    @property
    def data(self):
        return NewsItem(
            title=self.title_label.text(),
            content=self.content_textedit.toPlainText(),
        )

    @data.setter
    def data(self, d):
        self.title_label.setText(d.title)
        tc = self.content_textedit.textCursor()
        self.content_textedit.setPlainText(d.content)
        self.content_textedit.setTextCursor(tc)


class NewsItemDelegate(QtWidgets.QItemDelegate):
    def paint(self, painter, option, index):
        if isinstance(self.parent(), QtWidgets.QAbstractItemView):
            self.parent().openPersistentEditor(index)

    def createEditor(self, parent, option, index):
        data = index.data(QtCore.Qt.UserRole)
        editor = EditorWidget(data, parent)
        wrapper = partial(self.commitData.emit, editor)
        editor.editingFinished.connect(wrapper)
        model = index.model()
        model.setData(index, editor.sizeHint(), QtCore.Qt.SizeHintRole)
        return editor

    def setEditorData(self, editor, index):
        data = index.data(QtCore.Qt.UserRole)
        editor.data = data

    def setModelData(self, editor, model, index):
        model.setData(index, editor.data, QtCore.Qt.UserRole)
# ...

enter image description here

...