添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
听话的牛腩  ·  Python 执行 Bash ...·  昨天    · 
耍酷的草稿本  ·  GitHub - ...·  23 小时前    · 
豪爽的帽子  ·  Working with Python - ...·  23 小时前    · 
干练的瀑布  ·  Disk space used by a ...·  15 小时前    · 
挂过科的大蒜  ·  Oslas – Bergenas. ...·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I got the following code, which I slightly modified, as an answer on how to use HTML formatted text in a QListWidget .

main.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Dialog</class>
 <widget class="QDialog" name="Dialog">
  <property name="geometry">
    <x>0</x>
    <y>0</y>
    <width>341</width>
    <height>161</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Dialog</string>
  </property>
  <widget class="QWidget" name="verticalLayoutWidget">
   <property name="geometry">
     <x>10</x>
     <y>10</y>
     <width>321</width>
     <height>141</height>
    </rect>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout">
     <widget class="QListWidget" name="lwOptions"/>
    </item>
   </layout>
  </widget>
 </widget>
 <resources/>
 <connections/>

test.py

import os
import html
from PyQt5 import uic
from PyQt5.Qt import (QApplication, QDialog, QListWidget, 
    QListWidgetItem, QStyleOptionViewItem, 
    QStyledItemDelegate, QStyle)
from PyQt5.QtGui import QPalette, QAbstractTextDocumentLayout, QTextDocument
from PyQt5.QtCore import QSize
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 = 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()
        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, None)
        if index.column() != 0:
            textRect.adjust(5, 0, 0, 0)
        constant = 4
        margin = (option.rect.height() - options.fontMetrics.height()) // 2
        margin = margin - 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())
class GUI(QDialog):
    def __init__(self):
        super(GUI, self).__init__()
        dirname = os.path.dirname(os.path.abspath(__file__))
        uic.loadUi(os.path.join(dirname,'main.ui'), self)
        delegate = HTMLDelegate(self.lwOptions)
        self.lwOptions.setItemDelegate(delegate)
        for ordinal in ['first', 'second', 'third', 'fourth', 'fifth', 'sixth', 'seventh', 'eighth', 'ninth']:
            item = QListWidgetItem('This is the <b>{}</b> word. This is the <b>{}</b> word. This is the <b>{}</b> word.'.format(ordinal, ordinal, ordinal))
            self.lwOptions.addItem(item)
if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    window = GUI()
    window.show()
    sys.exit(app.exec_())

The code works fine, however, text that is longer than the width of the QListWidget is truncated and no horizontal scroll bar is displayed. (The vertical scroll bar is automatically added when needed.)

I tried forcing the display via ScrollBarAlwaysOn, which only displayed a non-working horizontal scroll bar.

How do I need to change the code to automatically add a horizontal scroll bar when needed?

The calculation I made in my previous answer was incorrect since the size that returns sizeHint() is relative to the previous item. A simple solution is to use the Qt::SizeHintRole role to set the size.

import os
from PyQt5 import QtCore, QtGui, QtWidgets, uic
class HTMLDelegate(QtWidgets.QStyledItemDelegate):
    def __init__(self, parent=None):
        super(HTMLDelegate, self).__init__(parent)
        self.doc = QtGui.QTextDocument(self)
    def paint(self, painter, option, index):
        painter.save()
        options = QtWidgets.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(QtWidgets.QStyle.CE_ItemViewItem, options, painter)
        ctx = QtGui.QAbstractTextDocumentLayout.PaintContext()
        if option.state & QtWidgets.QStyle.State_Selected:
            ctx.palette.setColor(QtGui.QPalette.Text, option.palette.color(
                QtGui.QPalette.Active, QtGui.QPalette.HighlightedText))
        else:
            ctx.palette.setColor(QtGui.QPalette.Text, option.palette.color(
                QtGui.QPalette.Active, QtGui.QPalette.Text))
        textRect = style.subElementRect(QtWidgets.QStyle.SE_ItemViewItemText, options, None)
        if index.column() != 0:
            textRect.adjust(5, 0, 0, 0)
        constant = 4
        margin = (option.rect.height() - options.fontMetrics.height()) // 2
        margin = margin - constant
        textRect.setTop(textRect.top() + margin)
        painter.translate(textRect.topLeft())
        painter.setClipRect(textRect.translated(-textRect.topLeft()))
        self.doc.documentLayout().draw(painter, ctx)
        painter.restore()
        s = QtCore.QSize(self.doc.idealWidth(), self.doc.size().height())
        index.model().setData(index, s, QtCore.Qt.SizeHintRole)
class GUI(QtWidgets.QDialog):
    def __init__(self):
        super(GUI, self).__init__()
        dirname = os.path.dirname(os.path.abspath(__file__))
        uic.loadUi(os.path.join(dirname,'main.ui'), self)
        delegate = HTMLDelegate(self.lwOptions)
        self.lwOptions.setItemDelegate(delegate)
        for ordinal in ['first', 'second', 'third', 'fourth', 'fifth', 'sixth', 'seventh', 'eighth', 'ninth']:
            item = QtWidgets.QListWidgetItem('This is the <b>{}</b> word. This is the <b>{}</b> word. This is the <b>{}</b> word.'.format(ordinal, ordinal, ordinal))
            self.lwOptions.addItem(item)
if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = GUI()
    window.show()
    sys.exit(app.exec_())
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.