Qt - QPushButton text formatting

26,351

Solution 1

You really don't need to subclass to change the formatting of your button, rather use stylesheets e.g.

QPushButton {
    font-size: 18pt;
    font-weight: bold;
    color: #ff0000;
}

Applying this to the button that you want to change will make the buttons text 18pt, bold and red. You can apply via widget->setStyleSheet()

Applying this to a widget in the hierarchy above will style all the buttons underneath, the QT stylesheet mechanism is very flexible and fairly well documented.

You can set stylesheets in the designer too, this will style the widget that you are editing immediately

Solution 2

you make the subclass of "QPushbutton", then override the paint event, there you modify the text to your wish.

here it is,

class button : public QPushButton
    {
    Q_OBJECT

public:
    button(QWidget *parent = 0)
        {

        }
    ~button()
        {

        }

    void paintEvent(QPaintEvent *p2)
        {

        QPushButton::paintEvent(p2);

            QPainter paint(this);
            paint.save();
            QFont sub(QApplication::font());
            sub.setPointSize(sub.pointSize() + 7);
            paint.setFont(sub);
            paint.drawText(QPoint(300,300),"Hi");
            paint.restore();

        }
    };

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);


    button b1;
    b1.showMaximized();
    return a.exec();
}

Solution 3

Note:
My answer is inspired by the idea from @Петър Петров and the comment from @mjwach.

You can subclass QPushButton and give it two private fields:

  • self.__lbl: A QLabel() instance to hold the rich text. Its background is made transparent and it doesn't catch mouse events.
  • self.__lyt: A QHBoxLayout() to hold the label. The layout margins are set to zero, such that the label's borders touch the button's borders. In other words: we ensure that the label has the exact same size as the button, and is positioned right on top of it.

Finally you have to override the setText() method, such that the text ends up in the label instead of the button.

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

Solution 4

You can subclass a QLabel and completely throw away all of its mouse events (so they reach the parent). Then crate a QPushButton, set a layout on it and in this layout insert a QLabel with formatted text. You get a button that contains QLabel and is clickable. (Any Qt Widget can have layout set, including ones that you never ever expected they can.)

Share:
26,351
Narek
Author by

Narek

Game developer.

Updated on August 09, 2020

Comments

  • Narek
    Narek over 3 years

    I have a QPushButton and on that I have a text and and icon. I want to make the text on the button to be bold and red. Looked at other forums, googled and lost my hope. Seems there is no way to do that if the button has an icon (of course if you don't create a new icon which is text+former icon). Is that the only way? Anyone has a better idea?

  • Narek
    Narek almost 14 years
    I have read that on the internet but have no idea what I should do. Could you add some details?
  • Narek
    Narek almost 14 years
    Honestly I don't understand what is written here, but tried to instantiate from your class instead of QPushButton, but it does not make any change.
  • Frank Osterfeld
    Frank Osterfeld almost 14 years
    I would avoid custom painting, as it will interfere with the style, button sizes etc. Narek: Did you try with Qt style sheets?
  • Narek
    Narek almost 14 years
    Have tried {font: 75 10pt "MS Shell Dlg 2"; color: rgb(170, 0, 0)} , but bold does not work. (Size and color work!).
  • Naruto
    Naruto almost 14 years
    @Narek, i have updated my code, i thought u only need how to subclass pushbutton, now i have also updated how to use this in main function. See you need to create the object of custom class button the paint event of button class handles the drawing,there you can draw as many strings as well as icons for the button at desired location
  • Harald Scheirich
    Harald Scheirich almost 14 years
    subclassing and custom drawing is overkill to this, nothing that can't be done through stylesheets
  • jjrv
    jjrv over 13 years
    This is overkill for styling the text but it's a very good starting point when the whole button needs to be styled. Thanks!
  • mjwach
    mjwach about 8 years
    This solution seems to be working pretty well for me! I had to do QWidget::setAttribute(Qt::WA_TranslucentBackground) to remove the label's background, and I used QWidget::setAttribute(Qt::WA_TransparentForMouseEvents) to cause mouse events to be ignored. (I think I could subclass the label and alter its event handler or whatever to accomplish that, but I guess the aforementioned widget attribute is good enough.) Also I had to give the push-button's layout a small left margin (maybe a right one is also needed?) and zeroed top and bottom margins to align the text decently.
  • Arnout
    Arnout over 2 years
    Adding self.__lbl.setAlignment(QtCore.Qt.AlignCenter | QtCore.Qt.AlignVCenter) to init helps center the label too