• 基于QToolButton封装,解决Icon不能设置hover和press态的问题


     1 #pragma once
     2 #include <QToolButton>
     3 #include <QBoxLayout>
     4 #include <QLabel>
     5 
     6 /* 基于QToolButton封装,解决Icon不能设置hover和press态的问题
     7 QSS使用方法:
     8     qproperty-dpiAdaptionImage: url(:/img/res/imgmainframe/icon_exit_presentation.png);
     9     qproperty-iconSize: 18px 18px;
    10     qproperty-buttonStyle:3; 对应ToolButtonStyle的枚举值,默认为2(左右)
    11     qproperty-space:16; icon和文字的间隔,默认是8
    12 */
    13 class CenteredToolButtonStyle;
    14 class IconTextButton : public QToolButton {
    15     Q_OBJECT
    16     Q_PROPERTY(QString dpiAdaptionImage READ getDpiAdaptionImage WRITE setDpiAdaptionImage)
    17     Q_PROPERTY(QString buttonType READ getButtonTypeFromQss WRITE setButtonTypeFromQss)
    18     Q_PROPERTY(QString buttonStyle READ getToolButtonStyleFromQss WRITE setToolButtonStyleFromQss)
    19     Q_PROPERTY(QString space READ getSpaceFromQss WRITE setSpaceFromQss)
    20 
    21     enum class ImageType
    22     {
    23         THREE_STATUS = 3,   //三态图片
    24         FOUR_STATUS = 4,    //四态图片
    25     };
    26 
    27     enum class ButtonStatus
    28     {
    29         NORMAL = 0,     //正常
    30         HOVER = 1,      //悬浮
    31         PRESS = 2,      //按下
    32         DISABLE = 3,    //禁用态
    33     };
    34 
    35 public:
    36     IconTextButton(QWidget* parent = nullptr, ImageType type = ImageType::THREE_STATUS);
    37     IconTextButton(const QString& text, QWidget* parent = nullptr, ImageType type = ImageType::THREE_STATUS);
    38 
    39 protected:
    40     QString getDpiAdaptionImage();
    41     void setDpiAdaptionImage(const QString& strIconPath);
    42     void setButtonTypeFromQss(const QString& strType);
    43     QString getButtonTypeFromQss();
    44     void setToolButtonStyleFromQss(const QString& strStyle);
    45     QString getToolButtonStyleFromQss();
    46     void setSpaceFromQss(const QString& strStyle);
    47     QString getSpaceFromQss();
    48 
    49     virtual void leaveEvent(QEvent* event) override;
    50     virtual void enterEvent(QEvent* event) override;
    51     virtual void mousePressEvent(QMouseEvent* event) override;
    52     virtual void mouseReleaseEvent(QMouseEvent* event) override;
    53     virtual void paintEvent(QPaintEvent* event) override;
    54     virtual void showEvent(QShowEvent* event) override;
    55 
    56 private:
    57     bool m_bLeftPress = false;
    58     ButtonStatus m_btnStatus = ButtonStatus::NORMAL;
    59     ImageType m_ImageType = ImageType::THREE_STATUS;
    60     int m_nImageWidth = 0;
    61     int m_nImageHeight = 0;
    62     QString m_strImagePath;
    63     QPixmap m_pixmap;
    64     Qt::ToolButtonStyle m_ToolButtonStyle = Qt::ToolButtonTextBesideIcon;
    65     CenteredToolButtonStyle* m_pCenteredToolButtonStyle = nullptr;
    66     int m_nSpace = 8;
    67 };

    .cpp

    #include "IconTextButton.h"
    #include "qevent.h"
    #include "CenteredToolButtonStyle.h"
    
     IconTextButton::IconTextButton(QWidget* parent /*= nullptr*/, ImageType type /*= IconPicType::THREE_STATUS*/)
        : IconTextButton("", parent, type) {
    }
    
     IconTextButton::IconTextButton(const QString& text, QWidget* parent /*= nullptr*/,
                                   ImageType type /*= IconPicType::THREE_STATUS*/)
        : QToolButton(parent)
        , m_ImageType(type) {
        setText(text);
        setToolButtonStyle(m_ToolButtonStyle);
     }
    
    void IconTextButton::setDpiAdaptionImage(const QString& strIconPath)
    {
        if (0 == strIconPath.compare(m_strImagePath)) {
            return;
        }
    
        m_strImagePath = strIconPath;
        m_pixmap.load(m_strImagePath);
        m_nImageWidth = m_pixmap.width() / static_cast<int>(m_ImageType);
        m_nImageHeight = m_pixmap.height();
    
        int nSub = static_cast<int>(m_btnStatus);
        QPixmap iconPixmap = m_pixmap.copy(m_nImageWidth * nSub, 0, m_nImageWidth, m_nImageHeight)
                .scaled(iconSize().width(), iconSize().height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
        setIcon(iconPixmap);
    }
    
    void IconTextButton::setButtonTypeFromQss(const QString& strType)
    {
        m_ImageType = static_cast<ImageType>(strType.toInt());
    }
    
    QString IconTextButton::getDpiAdaptionImage()
    {
        return m_strImagePath;
    }
    
    QString IconTextButton::getButtonTypeFromQss()
    {
        return QString("%1").arg(static_cast<int>(m_ImageType));
    }
    
    void IconTextButton::setToolButtonStyleFromQss(const QString& strStyle) {
        m_ToolButtonStyle = static_cast<Qt::ToolButtonStyle>(strStyle.toInt());
        setToolButtonStyle(m_ToolButtonStyle);
    }
    
    QString IconTextButton::getToolButtonStyleFromQss() {
        return QString("%1").arg(static_cast<int>(m_ToolButtonStyle));
    }
    
    void IconTextButton::setSpaceFromQss(const QString& strStyle) {
        m_nSpace = strStyle.toInt();
    }
    
    QString IconTextButton::getSpaceFromQss() {
        return QString("%1").arg(static_cast<int>(m_nSpace));
    }
    
    void IconTextButton::leaveEvent(QEvent* event)
    {
        __super::leaveEvent(event);
        m_btnStatus = ButtonStatus::NORMAL;
    }
    
    void IconTextButton::enterEvent(QEvent* event)
    {
        __super::enterEvent(event);
        m_btnStatus = ButtonStatus::HOVER;
    }
    
    void IconTextButton::mousePressEvent(QMouseEvent* event)
    {
        __super::mousePressEvent(event);
        if (event->button() == Qt::LeftButton)
        {
            m_bLeftPress = true;
            m_btnStatus = ButtonStatus::PRESS;
        }
    }
    
    void IconTextButton::mouseReleaseEvent(QMouseEvent* event)
    {
        __super::mouseReleaseEvent(event);
        if (m_bLeftPress)
        {
            m_bLeftPress = false;
            m_btnStatus = ButtonStatus::NORMAL;
        }
    }
    
    void IconTextButton::paintEvent(QPaintEvent* event) {
        __super::paintEvent(event);
    
        ButtonStatus status = m_btnStatus;
        if (isChecked()) {
            status = ButtonStatus::PRESS;
        }
    
        if (!isEnabled()) {
            status = ButtonStatus::DISABLE;
        }
    
        int nSub = static_cast<int>(status);
        QPixmap iconPixmap =
            m_pixmap.copy(m_nImageWidth * nSub, 0, m_nImageWidth, m_nImageHeight)
                .scaled(iconSize().width(), iconSize().height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
        setIcon(iconPixmap);
    
        // 自定义样式用于居中
        if (m_ToolButtonStyle == Qt::ToolButtonTextBesideIcon || m_ToolButtonStyle == Qt::ToolButtonTextUnderIcon) {
            if (m_pCenteredToolButtonStyle == nullptr) {
                m_pCenteredToolButtonStyle = new CenteredToolButtonStyle(this, m_ToolButtonStyle, iconSize(), m_nSpace);
                setStyle(m_pCenteredToolButtonStyle);
            }
        }
    }
    
    void IconTextButton::showEvent(QShowEvent* event)
    {
        QToolButton::showEvent(event);
        m_btnStatus = ButtonStatus::NORMAL;
        update();
    }

    自定义居中样式:

    .h

    #pragma once
    
    #include <QProxyStyle>
    #include <QToolButton>
    
    class CenteredToolButtonStyle : public QProxyStyle
    {
        Q_OBJECT
    
    public:
        CenteredToolButtonStyle(QToolButton* parent, Qt::ToolButtonStyle buttonStyle, const QSize& sIcon, const int& space);
    
        virtual void drawItemPixmap(QPainter* painter, const QRect& rect, int, const QPixmap& pixmap) const override;
        virtual void drawItemText(QPainter* painter, const QRect& rect, int flags, const QPalette& pal, bool enabled,
                                  const QString& text, QPalette::ColorRole textRole = QPalette::NoRole) const override;
        void Draw(QPainter* painter) const;
    
    private:
        const QToolButton* m_pParent = nullptr;
        const QSize m_iconSize;
        mutable QString m_text;
        mutable QPixmap m_pixMap;
        mutable QRect m_rect;
        mutable int m_nFlag = 0;
        mutable int m_ny = -1;
        mutable int m_nx = 1;
        mutable bool m_bEnabled = true;
        mutable QPalette m_palette;
        mutable QPalette::ColorRole m_textRole = QPalette::NoRole;
        bool m_bDrawFinished = false;
        Qt::ToolButtonStyle m_buttonStyle = Qt::ToolButtonTextBesideIcon;
        int m_nSpace = 8;
    };

    .cpp

    #include "CenteredToolButtonStyle.h"
    namespace {
    constexpr auto SPACE = 6;
    }
    
    CenteredToolButtonStyle::CenteredToolButtonStyle(QToolButton* parent, Qt::ToolButtonStyle buttonStyle,
                                                     const QSize& sIcon, const int& space)
        : QProxyStyle(),
        m_pParent(parent),
        m_iconSize(sIcon),
        m_buttonStyle(buttonStyle),
        m_nSpace(space)
    {
        if (parent != nullptr) {
            setParent(parent);
        }
    }
    
    void CenteredToolButtonStyle::drawItemPixmap(QPainter* painter, const QRect& rect, int, const QPixmap& pixmap) const {
        m_pixMap = pixmap;
        m_ny = rect.y();
        m_nx = rect.x();
        Draw(painter);
    }
    
    void CenteredToolButtonStyle::drawItemText(QPainter* painter, const QRect& rect, int flags, const QPalette& pal,
                                               bool enabled, const QString& text,
                                               QPalette::ColorRole textRole /* = QPalette::NoRole*/) const {
        m_text = text;
        m_rect = rect;
        m_nFlag = flags | Qt::AlignCenter;
        m_bEnabled = enabled;
        m_palette = pal;
        m_textRole = textRole;
        Draw(painter);
    }
    
    void CenteredToolButtonStyle::Draw(QPainter* painter) const {
        if (m_pParent == nullptr) {
            return;
        }
    
        if (m_buttonStyle == Qt::ToolButtonTextUnderIcon) {
            if (m_nx >= 0) {
                if (m_rect.x() != m_nx)
                    return;
                auto iconRect = m_rect;
                m_nx = 0;
                iconRect.adjust(0, -m_iconSize.height() - m_nSpace, 0,
                                -itemTextRect(m_pParent->fontMetrics(), m_rect, m_nFlag, m_bEnabled, m_text).height());
                QProxyStyle::drawItemPixmap(painter, iconRect, Qt::AlignCenter, m_pixMap);
            }
        } else if (m_buttonStyle == Qt::ToolButtonTextBesideIcon) {
            if (m_ny >= 0) {
                if (m_rect.y() != m_ny)
                    return;
                auto iconRect = m_rect;
                m_ny = 0;
                iconRect.adjust(-m_iconSize.width() - m_nSpace, 0,
                                -itemTextRect(m_pParent->fontMetrics(), m_rect, m_nFlag, m_bEnabled, m_text).width(), 0);
                QProxyStyle::drawItemPixmap(painter, iconRect, Qt::AlignCenter, m_pixMap);
            }
        }
    
        QProxyStyle::drawItemText(painter, m_rect, m_nFlag, m_palette, m_bEnabled, m_text, m_textRole);
    }
  • 相关阅读:
    2.16.8.内核启动的C语言阶段5
    2.16.7.内核启动的C语言阶段4
    2.16.6.内核启动的C语言阶段3
    2.16.5.内核启动的C语言阶段2
    JAVA_SE基础——34.static修饰成员变量
    JAVA_SE基础——33.this关键字的练习
    JAVA_SE基础——32.this关键字调用本类的构造方法
    JAVA_SE基础——31.this关键字
    JAVA类的方法调用和变量(全套)
    JAVA_SE基础——30.构造代码块
  • 原文地址:https://www.cnblogs.com/ForestCherry/p/16434716.html
Copyright © 2020-2023  润新知