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

基于QToolButton封装,解决Icon不能设置hover和press态的问题的更多相关文章

  1. 未能将基于用户的Visual C++项目设置保存到user文件错误的解决

    作者:朱金灿 来源:http://blog.csdn.net/clever101 最近遇见一个诡异错误,将Win7家庭版升级到Win7旗舰版.然后使用原来安装的VS2008开发,保存工程时总是出现未能 ...

  2. 基于jQuery封装的分页组件

    前言: 由于项目需要实现分页效果,上jQuery插件库找了下,但是木有找到自己想要的效果,于是自己封装了个分页组件. 思路: 主要是初始化时基于原型建立的分页模板然后绑定动态事件并实现刷新DOM的分页 ...

  3. iOS lanchImage 和icon的设置

    1 icon的设置 打开项目中的Assets.xcassets   这里边有一个icon 首先需要有icon 的尺寸 尺寸如下: 29*29   2x 29*29   3x 40*40  2x 40* ...

  4. 基于AFN封装的带缓存的网络请求

    给大家分享一个基于AFN封装的网络请求 git: https://github.com/zhouxihi/NVNetworking #带缓存机制的网络请求 各类请求有分带缓存 , 不带缓存, 可自定义 ...

  5. 基于vue-simple-uploader封装文件分片上传、秒传及断点续传的全局上传插件

    目录 1. 前言 2. 关于vue-simple-uploader 3. 基于vue-simple-uploader封装全局上传组件 4. 文件上传流程概览 5. 文件分片 6. MD5的计算过程 7 ...

  6. 基于epoll封装的事件回调miniserver

    epoll技术前两节已经阐述过了,目前主要做一下封装,很多epoll的服务器都是采用事件回调方式处理, 其实并没有什么复杂的,我慢慢给大家阐述下原理. 在networking.h和networking ...

  7. vue可视化图表 基于Echarts封装好的v-charts简介

    **vue可视化图表 基于Echarts封装好的v-charts** 近期公司又一个新的需求,要做一个订单和销售额统计的项目,需要用到可视化图表来更直观的展示数据.首先我想到的是Echarts,众所周 ...

  8. 基于better-scroll封装一个上拉加载下拉刷新组件

    1.起因 上拉加载和下拉刷新在移动端项目中是很常见的需求,遂自己便基于better-scroll封装了一个下拉刷新上拉加载组件. 2.过程 better-scroll是目前比较好用的开源滚动库,提供很 ...

  9. 基于layui,Jquery 表格动态编辑 设置 编辑值为 int 或者 double 类型及默认值

    首先先推荐大家在看这篇笔记时,阅读过我写的这篇 Layui表格编辑[不依赖Layui的动态table加载] 阅读过上面那篇笔记之后呢,才能更好的理解我现在所要说的这个东西 接下来废话不多说,上代码. ...

  10. 基于 React 封装的高德地图组件,帮助你轻松的接入地图到 React 项目中。

    react-amap 这是一个基于 React 封装的高德地图组件,帮助你轻松的接入地图到 React 项目中. 文档实例预览: Github Web | Gitee Web 特性 ️ 自动加载高德地 ...

随机推荐

  1. 再探 游戏 《 2048 》 —— AI方法—— 缘起、缘灭(1) —— Firefox浏览器下自动运行游戏篇

    四年前曾经写过一过博客: 对 游戏 < 2048 > 的一些思考 虽然过去几年了,但是这个游戏一直没有搞懂该怎么使用AI算法来进行求解,这里再次对这个问题进行一些探索. ========= ...

  2. MFC制作带界面的DLL库

    ## MFC如何创建一个带界面的DLL(动态链接库) 1.创建项目 打开VS,文件->新建->项目: 点击确定之后弹出来的界面,点击下一步->选择"使用共享MFC DLL的 ...

  3. 2023 ICPC网络赛第一场(A,D,J,L)

    2023 ICPC网络赛第一场(A,D,J,L) A Qualifiers Ranking Rules 先把两场比赛的学校排名处理出来,然后两场比赛的同位次进行合并即可 #include <bi ...

  4. 远程采集服务器指标信息(一) 远程通过SSH执行命令

    远程采集服务器信息,比如说磁盘信息.内存信息. 现介绍java通过SSH执行命令采集服务器信息,比如说执行df.ls.top. /** * * SSH远程执行shell类 */ public clas ...

  5. .NET 智能组件完全开源

    Daniel Roth在2024年3月20日发布了一篇文章: .NET 智能组件简介 – AI 驱动的 UI 控件.文章主要介绍了.NET Smart Components,这是一系列可以快速轻松地添 ...

  6. Devexpress GridView 单元格输入检验

    实现效果 打开设计器 找到CellValueChanged事件 编写代码 private void gvmain_CellValueChanged(object sender, DevExpress. ...

  7. 微信小程序 BLE 基础业务接口封装

    写在前面:本文所述未必符合当前最新情形(包括蓝牙技术发展.微信小程序接口迭代等). 微信小程序为蓝牙操作提供了很多接口,但在实际开发过程中,会发现隐藏了不少坑.目前主流蓝牙应用都是基于低功耗蓝牙(BL ...

  8. MacPorts 使用

    安装 安装苹果命令行开发工具: xcode-select --install 下载并打开 MacPorts 安装包. 使用 MacPorts 中的软件包称为 port. sudo port selfu ...

  9. Seata 1.3.0 ERROR i.s.c.r.n.NettyClientChannelManager -no available service 'null' found, please make sure registry config correct

    根据个人经验,报这个错误是因为nacos里并没有同步seata的config导致的 配置文档:https://www.bookstack.cn/read/seata-1.3.0/4b2f4de4831 ...

  10. vue动态绑定样式

    每次点击方块时通过三元表达式,改变对应的class,每一个不同的class对应不同的样式,从而通过改变class实现样式的切换. 实现代码 <template> <div class ...