【问题标题】:How to make item view render rich (html) text in PyQt?如何使项目视图在 PyQt 中呈现丰富的(html)文本?
【发布时间】:2011-02-26 22:34:03
【问题描述】:

我正在尝试在 python 中翻译来自this thread 的代码:

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

__data__ = [
        "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
        "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",
        "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.",
        "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
    ]

def get_html_box(text):
    return '''<table border="0" width="100%"><tr width="100%" valign="top">
        <td width="1%"><img src="softwarecenter.png"/></td>
        <td><table border="0" width="100%" height="100%">
        <tr><td><b><a href="http://www.google.com">titolo</a></b></td></tr>
        <tr><td>{0}</td></tr><tr><td align="right">88/88/8888, 88:88</td></tr>
        </table></td></tr></table>'''.format(text)

class HTMLDelegate(QStyledItemDelegate):

    def paint(self, painter, option, index):
        model = index.model()
        record = model.listdata[index.row()]
        doc = QTextDocument(self)
        doc.setHtml(get_html_box(record))
        doc.setTextWidth(option.rect.width())
        painter.save()
        ctx = QAbstractTextDocumentLayout.PaintContext()
        ctx.clip = QRectF(0, option.rect.top(), option.rect.width(), option.rect.height())
        dl = doc.documentLayout()
        dl.draw(painter, ctx)
        painter.restore()

    def sizeHint(self, option, index):
        model = index.model()
        record = model.listdata[index.row()]
        doc = QTextDocument(self)
        doc.setHtml(get_html_box(record))
        doc.setTextWidth(option.rect.width())
        return QSize(doc.idealWidth(), doc.size().height())

class MyListModel(QAbstractListModel):

    def __init__(self, parent=None, *args):
        super(MyListModel, self).__init__(parent, *args)
        self.listdata = __data__

    def rowCount(self, parent=QModelIndex()):
        return len(self.listdata)

    def data(self, index, role=Qt.DisplayRole):
        return index.isValid() and QVariant(self.listdata[index.row()]) or QVariant()

class MyWindow(QWidget):

    def __init__(self, *args):
        super(MyWindow, self).__init__(*args)
        # listview
        self.lv = QListView()
        self.lv.setModel(MyListModel(self))
        self.lv.setItemDelegate(HTMLDelegate(self))
        self.lv.setResizeMode(QListView.Adjust)
        # layout
        layout = QVBoxLayout()
        layout.addWidget(self.lv)
        self.setLayout(layout)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = MyWindow()
    w.show()
    sys.exit(app.exec_())

我猜元素的大小和位置计算不正确,可能是因为我根本不了解原始代码中与样式相关的部分。 有人可以帮我吗?

【问题讨论】:

  • 哪个元素的大小和位置没有被正确计算?你能解释一下你的预期吗?
  • 对我来说,每个元素的计算高度都是错误的:当我运行该代码时,列表仅显示顶部元素,高于应有的高度(下面有很多空白),我不能看不到其他元素。

标签: python pyqt qlistview qstyleditemdelegate


【解决方案1】:

代码不尊重所需的目标绘图区域 (option.rect):

ctx.clip = QRectF(0, option.rect.top(), option.rect.width(), option.rect.height())

上面剪辑了QTextDocument绘制到指定区域的部分。您真的想翻译画家,以便它在矩形的topLeft() 处开始绘画,然后延伸到指定的宽度和高度。由于documentLayout() 假设画家在原点(即在它应该绘制的位置),所以这是修复:

def paint(self, painter, option, index):
    model = index.model()
    record = model.listdata[index.row()]
    doc = QTextDocument(self)
    doc.setHtml(get_html_box(record))
    doc.setTextWidth(option.rect.width())
    ctx = QAbstractTextDocumentLayout.PaintContext()

    painter.save()
    painter.translate(option.rect.topLeft());
    painter.setClipRect(option.rect.translated(-option.rect.topLeft()))
    dl = doc.documentLayout()
    dl.draw(painter, ctx)
    painter.restore()

【讨论】:

  • 我明白了。我真的需要大量学习才能理解为什么像这样的常见任务需要这么多代码。也许我选择了最糟糕的方式来做到这一点。顺便说一句,非常感谢您的更正。
  • @GiorgioGelardi 我实际上认为正是这些让 QT 有点不成熟。默认情况下,ListViews 中的富文本很容易包含在 QT 中(见鬼,他们只需要复制这段代码),而且非常宝贵!
  • 这段代码仍然会导致在每个项目下方看到很大的空白区域(高度计算错误)?
猜你喜欢
  • 2010-12-29
  • 1970-01-01
  • 2021-11-14
  • 1970-01-01
  • 1970-01-01
  • 2015-12-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多