• Qt::QProxyStyle


    QProxyStyle 修改控件默认系统样式,用于动态覆盖绘图或其他特定的样式行为。
    
    实现自定义样式,需要自己定义一个类,从QProxyStyle派生,实现对应的虚函数即可。
    #include <QProxyStyle>
    #include <QPalette>
    
    QT_BEGIN_NAMESPACE
    class QPainterPath;
    QT_END_NAMESPACE
    
    class NorwegianWoodStyle : public QProxyStyle
    {
        Q_OBJECT
    
    public:
        NorwegianWoodStyle();
    
        QPalette standardPalette() const override;
    
        void polish(QWidget *widget) override;
        void unpolish(QWidget *widget) override;
        int pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const override;
        int styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const override;
        void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const override;
        void drawControl(ControlElement control, const QStyleOption *option, QPainter *painter, const QWidget *widget) const override;
    
    private:
        static void setTexture(QPalette &palette, QPalette::ColorRole role, const QImage &image);
        static QPainterPath roundRectPath(const QRect &rect);
        mutable QPalette m_standardPalette;
    };
    #include <QComboBox>
    #include <QPainter>
    #include <QPushButton>
    #include <QStyleFactory>
    
    NorwegianWoodStyle::NorwegianWoodStyle() :
        QProxyStyle(QStyleFactory::create("windows"))
    {
        setObjectName("NorwegianWood");
    }
    
    QPalette NorwegianWoodStyle::standardPalette() const
    {
        if (!m_standardPalette.isBrushSet(QPalette::Disabled, QPalette::Mid)) {
            QColor brown(212, 140, 95);
            QColor beige(236, 182, 120);
            QColor slightlyOpaqueBlack(0, 0, 0, 63);
    
            QImage backgroundImage(":/images/woodbackground.png");
            QImage buttonImage(":/images/woodbutton.png");
            QImage midImage = buttonImage.convertToFormat(QImage::Format_RGB32);
    
            QPainter painter;
            painter.begin(&midImage);
            painter.setPen(Qt::NoPen);
            painter.fillRect(midImage.rect(), slightlyOpaqueBlack);
            painter.end();
     
            QPalette palette(brown);
    
            palette.setBrush(QPalette::BrightText, Qt::white);
            palette.setBrush(QPalette::Base, beige);
            palette.setBrush(QPalette::Highlight, Qt::darkGreen);
            setTexture(palette, QPalette::Button, buttonImage);
            setTexture(palette, QPalette::Mid, midImage);
            setTexture(palette, QPalette::Window, backgroundImage);
    
            QBrush brush = palette.window();
            brush.setColor(brush.color().darker());
    
            palette.setBrush(QPalette::Disabled, QPalette::WindowText, brush);
            palette.setBrush(QPalette::Disabled, QPalette::Text, brush);
            palette.setBrush(QPalette::Disabled, QPalette::ButtonText, brush);
            palette.setBrush(QPalette::Disabled, QPalette::Base, brush);
            palette.setBrush(QPalette::Disabled, QPalette::Button, brush);
            palette.setBrush(QPalette::Disabled, QPalette::Mid, brush);
    
            m_standardPalette = palette;
        }
    
        return m_standardPalette;
    }
    
    void NorwegianWoodStyle::polish(QWidget *widget)
    
    {
        if (qobject_cast<QPushButton *>(widget)
                || qobject_cast<QComboBox *>(widget))
            widget->setAttribute(Qt::WA_Hover, true);
    }
    
    void NorwegianWoodStyle::unpolish(QWidget *widget)
    {
        if (qobject_cast<QPushButton *>(widget)
                || qobject_cast<QComboBox *>(widget))
            widget->setAttribute(Qt::WA_Hover, false);
    }
    
    int NorwegianWoodStyle::pixelMetric(PixelMetric metric,
                                        const QStyleOption *option,
                                        const QWidget *widget) const
    {
        switch (metric) {
        case PM_ComboBoxFrameWidth:
            return 8;
        case PM_ScrollBarExtent:
            return QProxyStyle::pixelMetric(metric, option, widget) + 4;
        default:
            return QProxyStyle::pixelMetric(metric, option, widget);
        }
    }
    
    int NorwegianWoodStyle::styleHint(StyleHint hint, const QStyleOption *option,
                                      const QWidget *widget,
                                      QStyleHintReturn *returnData) const
    {
        switch (hint) {
        case SH_DitherDisabledText:
            return int(false);
        case SH_EtchDisabledText:
            return int(true);
        default:
            return QProxyStyle::styleHint(hint, option, widget, returnData);
        }
    }
    
    void NorwegianWoodStyle::drawPrimitive(PrimitiveElement element,
                                               const QStyleOption *option,
                                               QPainter *painter,
                                               const QWidget *widget) const
    {
        switch (element) 
        {
        case PE_PanelButtonCommand:
            {
                int delta = (option->state & State_MouseOver) ? 64 : 0;
                QColor slightlyOpaqueBlack(0, 0, 0, 63);
                QColor semiTransparentWhite(255, 255, 255, 127 + delta);
                QColor semiTransparentBlack(0, 0, 0, 127 - delta);
    
                int x, y, width, height;
                option->rect.getRect(&x, &y, &width, &height);
                
                QPainterPath roundRect = roundRectPath(option->rect);
                int radius = qMin(width, height) / 2;
                QBrush brush;
                bool darker;
    
                const QStyleOptionButton *buttonOption =
                        qstyleoption_cast<const QStyleOptionButton *>(option);
                if (buttonOption
                        && (buttonOption->features & QStyleOptionButton::Flat)) {
                    brush = option->palette.window();
                    darker = (option->state & (State_Sunken | State_On));
                } else {
                    if (option->state & (State_Sunken | State_On)) {
                        brush = option->palette.mid();
                        darker = !(option->state & State_Sunken);
                    } else {
                        brush = option->palette.button();
                        darker = false;
                    }
                }
    
                painter->save();
                painter->setRenderHint(QPainter::Antialiasing, true);
                painter->fillPath(roundRect, brush);
    
                if (darker)
                    painter->fillPath(roundRect, slightlyOpaqueBlack);
    
                int penWidth;
    
                if (radius < 10)
                    penWidth = 3;
                else if (radius < 20)
                    penWidth = 5;
                else
                    penWidth = 7;
    
                QPen topPen(semiTransparentWhite, penWidth);
                QPen bottomPen(semiTransparentBlack, penWidth);
    
                if (option->state & (State_Sunken | State_On))
                    qSwap(topPen, bottomPen);
    
                int x1 = x;
                int x2 = x + radius;
                int x3 = x + width - radius;
                int x4 = x + width;
    
                if (option->direction == Qt::RightToLeft) {
                    qSwap(x1, x4);
                    qSwap(x2, x3);
                }
    
                QPolygon topHalf;
                topHalf << QPoint(x1, y)
                        << QPoint(x4, y)
                        << QPoint(x3, y + radius)
                        << QPoint(x2, y + height - radius)
                        << QPoint(x1, y + height);
    
                painter->setClipPath(roundRect);
                painter->setClipRegion(topHalf, Qt::IntersectClip);
                painter->setPen(topPen);
                painter->drawPath(roundRect);
    
                QPolygon bottomHalf = topHalf;
                bottomHalf[0] = QPoint(x4, y + height);
    
                painter->setClipPath(roundRect);
                painter->setClipRegion(bottomHalf, Qt::IntersectClip);
                painter->setPen(bottomPen);
                painter->drawPath(roundRect);
    
                painter->setPen(option->palette.windowText().color());
                painter->setClipping(false);
                painter->drawPath(roundRect);
    
                painter->restore();
            }
            break;
        default:
            QProxyStyle::drawPrimitive(element, option, painter, widget);
        }
    }
    
    void NorwegianWoodStyle::drawControl(ControlElement element,
        const QStyleOption *option,
        QPainter *painter,
        const QWidget *widget) const
    {
        switch (element) {
        case CE_PushButtonLabel:
            {
                QStyleOptionButton myButtonOption;
                const QStyleOptionButton *buttonOption =
                        qstyleoption_cast<const QStyleOptionButton *>(option);
                if (buttonOption) {
                    myButtonOption = *buttonOption;
                    if (myButtonOption.palette.currentColorGroup()
                            != QPalette::Disabled) {
                        if (myButtonOption.state & (State_Sunken | State_On)) {
                            myButtonOption.palette.setBrush(QPalette::ButtonText,
                                    myButtonOption.palette.brightText());
                        }
                    }
                }
                QProxyStyle::drawControl(element, &myButtonOption, painter, widget);
            }
            break;
        default:
            QProxyStyle::drawControl(element, option, painter, widget);
        }
    }
    
    void NorwegianWoodStyle::setTexture(QPalette &palette, QPalette::ColorRole role, const QImage &image)
    {
        for (int i = 0; i < QPalette::NColorGroups; ++i) {
            QBrush brush(image);
            brush.setColor(palette.brush(QPalette::ColorGroup(i), role).color());
            palette.setBrush(QPalette::ColorGroup(i), role, brush);
        }
    }
    
    QPainterPath NorwegianWoodStyle::roundRectPath(const QRect &rect)
    {
        int radius = qMin(rect.width(), rect.height()) / 2;
        int diam = 2 * radius;
    
        int x1, y1, x2, y2;
        rect.getCoords(&x1, &y1, &x2, &y2);
    
        QPainterPath path;
        path.moveTo(x2, y1 + radius);
        path.arcTo(QRect(x2 - diam, y1, diam, diam), 0.0, +90.0);
        path.lineTo(x1 + radius, y1);
        path.arcTo(QRect(x1, y1, diam, diam), 90.0, +90.0);
        path.lineTo(x1, y2 - radius);
        path.arcTo(QRect(x1, y2 - diam, diam, diam), 180.0, +90.0);
        path.lineTo(x1 + radius, y2);
        path.arcTo(QRect(x2 - diam, y2 - diam, diam, diam), 270.0, +90.0);
        path.closeSubpath();
        return path;
    }
    void changeStyle(const QString &styleName)
    {
        if (styleName == "NorwegianWood")
            QApplication::setStyle(new NorwegianWoodStyle);
        else
            QApplication::setStyle(QStyleFactory::create(styleName));
    }
  • 相关阅读:
    2021.2.5 学习总结
    2021.2.1 学习总结
    2021.2.4 学习总结
    学习:C#中struct与class的区别(转)
    学习:DirectoryEntry::Path 属性(winnt、LDAP、IIS)(转)
    学习:Asp.net页面传值总结(转)
    学习:WinForm分页控件(转)
    学习:c#中抽象类和接口的相同点跟区别(转)
    学习:C#中获取当前路径的几种方法(转)
    记录:new关键字、new修饰符、new约束
  • 原文地址:https://www.cnblogs.com/osbreak/p/15734167.html
Copyright © 2020-2023  润新知