QPushButton icon aligned left with text centered

后端 未结 3 1189
悲&欢浪女
悲&欢浪女 2020-12-17 14:21

In my Qt 5.7.1 application I\'ve some buttons, I want to align button\'s icons to left and centre text, but there is no option in designer to do this.

I can

3条回答
  •  清酒与你
    2020-12-17 14:50

    To get this level of control you will need to write some code to override the style for your platform. This is best done using a QProxyStyle. In this case we are looking for when the style is asked to draw a CE_PushButtonLabel (the label includes the icon, and they are hard coded in Qt to be aligned together).

    You need to implement a QProxyStyle and override the drawControl() method. The code for the bulk of it is copied directly from the Qt source code for the default drawcontrol method (in qcommonstyle.cpp) - so although it looks lengthy, it is mostly doing what Qt already does. I put extra /****/ markers around the sections I modified. This won't show up in Qt Designer, but will work at runtime.

    Final result (shown on mac, should match platform you're on)

    main.cpp:

    QApplication a(argc, argv);
    a.setStyle(new MyStyle);
    ...
    

    mystyle.h

     class MyStyle : public QProxyStyle
     {
     public:
    
     virtual void drawControl(ControlElement element, const QStyleOption *opt,
                   QPainter *p, const QWidget *widget = Q_NULLPTR) const;
     };
    

    mystyle.cpp

    // Copied from Qt source code..
    static QWindow *qt_getWindow(const QWidget *widget)
    {
        return widget ? widget->window()->windowHandle() : 0;
    }
    
    void MyStyle::drawControl(ControlElement element, const QStyleOption *opt, QPainter *p, const QWidget *widget) const
    {
        if(element==CE_PushButtonLabel)
        {
            if (const QStyleOptionButton *button = qstyleoption_cast(opt))
            {
                    QRect textRect = button->rect;
                    uint tf = Qt::AlignVCenter | Qt::TextShowMnemonic;
                    if (!proxy()->styleHint(SH_UnderlineShortcut, button, widget))
                        tf |= Qt::TextHideMnemonic;
    
                    if (!button->icon.isNull()) {
                        QRect iconRect;
                        QIcon::Mode mode = button->state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
                        if (mode == QIcon::Normal && button->state & State_HasFocus)
                            mode = QIcon::Active;
                        QIcon::State state = QIcon::Off;
                        if (button->state & State_On)
                            state = QIcon::On;
    
                        QPixmap pixmap = button->icon.pixmap(qt_getWindow(widget), button->iconSize, mode, state);
    
                        int pixmapWidth = pixmap.width() / pixmap.devicePixelRatio();
                        int pixmapHeight = pixmap.height() / pixmap.devicePixelRatio();
                        int labelWidth = pixmapWidth;
                        int labelHeight = pixmapHeight;
                        int iconSpacing = 4;//### 4 is currently hardcoded in QPushButton::sizeHint()
                        int textWidth = button->fontMetrics.boundingRect(opt->rect, tf, button->text).width();
                        if (!button->text.isEmpty())
                            labelWidth += (textWidth + iconSpacing);
    
                        /*************************************************************/
                        // Make the icon rectangle always be 10px in from the left edge
                        /*************************************************************/
                        iconRect = QRect(10,
                                         textRect.y() + (textRect.height() - labelHeight) / 2,
                                         pixmapWidth, pixmapHeight);
    
                        iconRect = visualRect(button->direction, textRect, iconRect);
    
                        /***********************************/
                        // Always horizontal align the text
                        /***********************************/
                        tf |= Qt::AlignHCenter;
    
    
                        if (button->state & (State_On | State_Sunken))
                            iconRect.translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, opt, widget),
                                               proxy()->pixelMetric(PM_ButtonShiftVertical, opt, widget));
                        p->drawPixmap(iconRect, pixmap);
                    } else {
                        tf |= Qt::AlignHCenter;
                    }
                    if (button->state & (State_On | State_Sunken))
                        textRect.translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, opt, widget),
                                     proxy()->pixelMetric(PM_ButtonShiftVertical, opt, widget));
    
                    if (button->features & QStyleOptionButton::HasMenu) {
                        int indicatorSize = proxy()->pixelMetric(PM_MenuButtonIndicator, button, widget);
                        if (button->direction == Qt::LeftToRight)
                            textRect = textRect.adjusted(0, 0, -indicatorSize, 0);
                        else
                            textRect = textRect.adjusted(indicatorSize, 0, 0, 0);
                    }
                    proxy()->drawItemText(p, textRect, tf, button->palette, (button->state & State_Enabled),
                                 button->text, QPalette::ButtonText);
                }
                return;
        }
    
        // For all other controls, draw the default
        QProxyStyle::drawControl(element, opt, p, widget);
    }
    

提交回复
热议问题