基于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);
}

 

posted @ 2022-07-01 15:06  水云间月掌柜  阅读(819)  评论(0编辑  收藏  举报