Использование HTML тегов в названии кнопки PyQt6

Рейтинг: 0Ответов: 2Опубликовано: 04.05.2023

В своем проекте на PyQt6 я с легкостью пользовался HTML тегами в таких элементах, как QLabel:

l = QLabel('<span>Something</span><b>text</b>')

Но я никогда не пробовал применять их в других. Сейчас мне понадобилось вставить теги в название QPushButton. Я попробовал тоже самое:

btn = QPushButton('<span>text</span>')

Но здесь уже они экранируются, и я пока что не нагуглил каким образом можно обойти эту проблему. Есть ли какое нибудь решение?

Ответы

▲ 1

Можно отрисовать руками в paintEvent - сначала нарисовать пустую кнопку, а потом в ней richtext

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


class QMyPushButton(QPushButton):

    def __init__(self, parent):
        super().__init__(parent)

    def paintEvent(self, event):
        # Текст запомним и обнулим, чтобы отрисовать кнопку без текста
        text = self.text()
        self.setText('')
        # оригинальный paintEvent отрисует кнопку без текста
        super().paintEvent(event)
        self.setText(text)
        # отрисовываем RichText
        qp = QtGui.QPainter()
        qp.begin(self)
        # центрирование надписи придется вам реализовывать самостоятельно
        top_left = QtCore.QPoint(10, 15)
        qp.drawStaticText(top_left, QtGui.QStaticText(text))
        qp.end()


class MainWindow(QMainWindow):

    def __init__(self):
        super().__init__()
        self.central_widget = QWidget(self)
        self.setCentralWidget(self.central_widget)
        self.btn = QMyPushButton(self.central_widget)
        self.btn.resize(150, 50)
        self.btn.move(30,20)
        self.btn.setText('<i>hello</i> <font color="red">amazing</font> <b>world</b>')


if __name__ == '__main__':
    
    app = QApplication(sys.argv)
    main_window = MainWindow()
    main_window.show()
    sys.exit(app.exec_())
    
▲ 0

Все таки нашел решение через переопределение класса QPushButton. Фишка заключается в том, что внутри можно создать экземпляры QLabel и использовать их вместо родного тайтла кнопки (понадобится создать компоновщик). Также нужно переопределить метод setText() и sizeHint():

class RichTextPushButton(QPushButton):
    def __init__(self, parent=None, text=None):
        if parent is not None:
            super().__init__(parent)
        else:
            super().__init__()
        self.__lbl = QLabel(self)
        if text is not None:
            self.__lbl.setText(text)
        self.__lyt = QHBoxLayout()
        self.__lyt.setContentsMargins(0, 0, 0, 0)
        self.__lyt.setSpacing(0)
        self.setLayout(self.__lyt)
        self.__lbl.setAttribute(Qt.WA_TranslucentBackground)
        self.__lbl.setAttribute(Qt.WA_TransparentForMouseEvents)
        self.__lbl.setSizePolicy(
            QSizePolicy.Expanding,
            QSizePolicy.Expanding,
        )
        self.__lbl.setTextFormat(Qt.RichText)
        self.__lyt.addWidget(self.__lbl)
        return

    def setText(self, text):
        self.__lbl.setText(text)
        self.updateGeometry()
        return

    def sizeHint(self):
        s = QPushButton.sizeHint(self)
        w = self.__lbl.sizeHint()
        s.setWidth(w.width())
        s.setHeight(w.height())
        return s

Вместе с тем убираем фон и ивенты связанные с мышью на лэйблах.

PS: Стоит отметить, что тем не менее форматирование в этом случае заметно более ограничено, чем в нативном HTML и CSS. К примеру нельзя прикрутить к span'у border-radius. Он просто на него не реагирует. Но все же это лучше, чем ничего.