PyQt listview与html富文本委托移动文本位不合适(包括图片和代码)

时间:2015-05-11 19:03:51

标签: qt listview delegates pyqt pyside

gif showing with delegate and without

有一个列表视图,其中项目需要使用粗体文本,因此html委托是要走的路。我环顾四周,找到了几个解决方案,其中我创建了这个代码,但它有一个问题,你可以在gif中看到,它显示了使用委托和没有的结果。

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys

class HTMLDelegate(QStyledItemDelegate):
    def __init__(self, parent=None):
        super(HTMLDelegate, self).__init__(parent)
        self.doc = QTextDocument(self)

    def paint(self, painter, option, index):
        painter.save()

        options = QStyleOptionViewItemV4(option)
        self.initStyleOption(options, index)

        self.doc.setHtml(options.text)
        options.text = ""

        style = QApplication.style() if options.widget is None \
            else options.widget.style()
        style.drawControl(QStyle.CE_ItemViewItem, options, painter)

        ctx = QAbstractTextDocumentLayout.PaintContext()

        if option.state & QStyle.State_Selected:
            ctx.palette.setColor(QPalette.Text, option.palette.color(
                                 QPalette.Active, QPalette.HighlightedText))

        textRect = style.subElementRect(QStyle.SE_ItemViewItemText, options)
        painter.translate(textRect.topLeft())
        self.doc.documentLayout().draw(painter, ctx)

        painter.restore()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    data = ['1','2','3','4','5','6','7','8','9']
    main_list = QListView()
    main_list.setItemDelegate(HTMLDelegate())
    main_list.setModel(QStringListModel(data))
    main_list.show()
    sys.exit(app.exec_())

以下是PyQt5PySide版本

我不使用sizeHint,因为通过我的测试它并不觉得它影响了这种行为。 有些属性错误地定位了文本,我已经能够部分地反驳它:

self.doc.setDocumentMargin(0)

默认边距为4,然后将整个项目位移到右侧

rect = options.rect
options.rect = QRect(rect.x()+3, rect.y(), rect.width(), rect.height())

但是我不认为它解决了这个问题的原因,只是掩盖了它,一旦你尝试添加icons for example

它就会再次出现问题

3 个答案:

答案 0 :(得分:2)

现在这个是我使用的那个

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
import sys

class HTMLDelegate(QStyledItemDelegate):
    def __init__(self, parent=None):
        super().__init__()
        self.doc = QTextDocument(self)

    def paint(self, painter, option, index):
        painter.save()

        options = QStyleOptionViewItem(option)

        self.initStyleOption(options, index)
        self.doc.setHtml(options.text)
        options.text = ""

        style = QApplication.style() if options.widget is None \
            else options.widget.style()
        style.drawControl(QStyle.CE_ItemViewItem, options, painter)

        ctx = QAbstractTextDocumentLayout.PaintContext()

        print(QStyle.State_Selected)

        if option.state & QStyle.State_Selected:
            ctx.palette.setColor(QPalette.Text, option.palette.color(
                QPalette.Active, QPalette.HighlightedText))
        else:
            ctx.palette.setColor(QPalette.Text, option.palette.color(
                QPalette.Active, QPalette.Text))

        textRect = style.subElementRect(
            QStyle.SE_ItemViewItemText, options)

        if index.column() != 0:
            textRect.adjust(5, 0, 0, 0)

        thefuckyourshitup_constant = 4
        margin = (option.rect.height() - options.fontMetrics.height()) // 2
        margin = margin - thefuckyourshitup_constant
        textRect.setTop(textRect.top() + margin)

        painter.translate(textRect.topLeft())
        painter.setClipRect(textRect.translated(-textRect.topLeft()))
        self.doc.documentLayout().draw(painter, ctx)

        painter.restore()

    def sizeHint(self, option, index):
        return QSize(self.doc.idealWidth(), self.doc.size().height())

if __name__ == '__main__':
    app = QApplication(sys.argv)
    data = ['1','2','3','4','5','6','7','8','9']
    main_list = QListView()
    main_list.setItemDelegate(HTMLDelegate())
    main_list.setModel(QStringListModel(data))
    main_list.show()
    sys.exit(app.exec_())

答案 1 :(得分:1)

经过多次挖掘和尝试之后,调整文本矩形似乎让人觉得一切都很好,并且似乎在各种DE中表现一致

    textRect.adjust(-1, -4, 0, 0)

我不确定它是否是一个错误,但人们会期望SE_ItemViewItemText应该自己给出正确的位置

答案 2 :(得分:0)

一个老问题,但是由于我遇到了类似的问题,因此我想我将解决您的代码中的一些问题。通常,它是self.doc成员。它不会像您希望的那样起作用。在多次调用paint()之前,将多次调用sizeHint()方法,并将获得一个空文档(这就是为什么您“不觉得它正在影响这种行为”的原因)。

您可能会想到,只需在sizeHint()与paint()中初始化文档即可,但这也是错误的。列表中只有一个委托和文档,因此该文档将始终基于最后一个尺寸或颜色,因此以self.doc作为成员只会节省您的文档结构,考虑到它的混乱可能不值得原因。