QLabel重绘实现圆角矩形图片/文本和图片同时显示

QLabel一般用于显示一段文字,这段文字可以被鼠标选中/复制,也可是设置自动换行等,还可以用于显示图片。

但是使用QLabel显示图片时,qss样式设置的圆角radius属性是不生效的。

QLabel显示纯文本时,设置了背景颜色后,border-radius圆角属性是生效的,但是显示QPixmap图片时,圆角属性会失效,另外一个QLabel无法同时显示图片和文本(设置富文本的方式可以但是不灵活图片和文字间距无法调整):

所以我对QLabel需求是:

1.显示图片时,可以给图片设置圆角;

2.图片和文本可以同时显示,且可以设置图片在文字的左边或者右边,间距也可以调整,甚至文本会随尺寸变化,当不能完全显示是变成省略号截断(右边截断,中间截断,左边截断);

以上两点需求都是原生QLbel无法支持的,所以需要继承QLbel重绘。

以下代码是简陋实现的Demo,看懂了你需要自己去完善它,封装成更加通用的控件,例如:提供更多接口去设置上下左右内边距,子控件间距,图片尺寸,图片在文本的上下左右等。。。使劲魔改成适合自己的Label吧

mylabel.h

#ifndef MYLABEL_H
#define MYLABEL_H#include <QLabel>class MyLabel : public QLabel
{
public:MyLabel(QWidget *parent=nullptr, Qt::WindowFlags f=Qt::WindowFlags());void setPixmap(const QPixmap &pix);protected:void paintEvent(QPaintEvent *event) override;private:int m_leftPadding;int m_rightPadding;int m_topPadding;int m_bottomPadding;int m_spacing;QSize m_iconSize;QPixmap m_pixmap;
};#endif // MYLABEL_H

mylabel.cpp

#include "mylabel.h"
#include <QPaintEvent>
#include <QPainter>
#include <QPainterPath>MyLabel::MyLabel(QWidget *parent, Qt::WindowFlags f) :QLabel(parent,f)
{m_leftPadding = 10;m_rightPadding = 10;m_topPadding = 10;m_bottomPadding = 10;m_spacing = 10;m_iconSize = QSize(64,64);// 获取 QLabel 中文本所使用的字体尺寸QFont labelFont = this->font(); // 获取 QLabel 的字体QFontMetrics fontMetrics(labelFont); // 使用 QFontMetrics 获取字体尺寸信息int textHeight = fontMetrics.height(); // 获取文本高度int h = textHeight + m_topPadding + m_bottomPadding;this->setMinimumHeight(h);this->setMinimumWidth(textHeight*2);}void MyLabel::setPixmap(const QPixmap &pix)
{m_pixmap = pix;
}void MyLabel::paintEvent(QPaintEvent *event)
{QPainter painter(this);painter.setClipRect(event->rect());painter.setRenderHints(QPainter::Antialiasing|QPainter::TextAntialiasing|QPainter::SmoothPixmapTransform,true);painter.setFont(this->font()); // 设置绘制文本的字体QPalette palette = this->palette(); // 获取QSS样式中设置的调色板QColor textColor = palette.color(QPalette::WindowText); // 获取文本颜色painter.setBrush(Qt::NoBrush);painter.setPen(textColor);// 绘制图标/图片if(!m_pixmap.isNull()){int h = m_iconSize.height() + m_topPadding + m_bottomPadding;this->setMinimumHeight(h);this->setMinimumWidth(m_iconSize.width() + m_leftPadding + m_rightPadding);QPixmap pix = m_pixmap.scaled(m_iconSize,Qt::IgnoreAspectRatio,Qt::SmoothTransformation);QPainterPath pImgPah;QRect rImage(m_leftPadding,m_topPadding,m_iconSize.width(),m_iconSize.height());pImgPah.addRoundedRect(rImage,10,10);// 给路径添加一个圆角矩形区域,rImage就是图像要显示的地方的rect,然后10.0,10.0是指x和y的圆角半径。painter.setClipPath(pImgPah);// 裁剪路径(把矩形裁剪成圆角矩形)painter.drawPixmap(rImage,pix);// 把图像画在被裁剪后的目标区域painter.setClipping(false);// 结束裁剪// 绘制文本QRect textRect = event->rect();textRect = textRect.adjusted(m_leftPadding,m_topPadding,-m_rightPadding,-m_bottomPadding);textRect = textRect.adjusted(m_iconSize.width()+m_spacing,0,0,0);// 图标与文本的间距// 判断空间是否足够容纳文本,不够则省略号右截断模式QFontMetrics fontMetrics(this->font());QString elidedText = fontMetrics.elidedText(this->text(), Qt::ElideRight, textRect.width());painter.drawText(textRect,Qt::AlignVCenter|Qt::AlignLeft,elidedText);}else{// 绘制纯文本QRect textRect = event->rect();textRect = textRect.adjusted(m_leftPadding,m_topPadding,-m_rightPadding,-m_bottomPadding);painter.setBrush(Qt::NoBrush);// 判断空间是否足够容纳文本,不够则省略号右截断模式QFontMetrics fontMetrics(this->font());QString elidedText = fontMetrics.elidedText(this->text(), Qt::ElideRight, textRect.width());painter.drawText(textRect,Qt::AlignVCenter|Qt::AlignLeft,elidedText);}
}

注意:重写paintEvent后会导致原生QLabel支持的鼠标选中文本复制的功能异常,所以此种方式重绘不支持文本选中复制,需要自己想办法重写文本选中复制功能。由于文本选中复制功能过于复杂,一般需要文本复制功能的话我就直接使用QLabel了。

使用效果:

先给MyLabel设置QLabel的QSS(由于MyLabel是继承自QLabel所以可以使用它的部分qss属性例如:字体,字体颜色等,但是其他属性(background,border等)是无效的)

QLabel
{color: rgb(88, 148, 67);font-size:16px;
}

一个MyLabel同时显示圆角图片和文本,文本支持随尺寸变化而右边省略号截断;

再补充一种非绘制手段将QPixmap的直角图片处理成圆角的QPixmap图片,直接塞给QLabel显示,此种方法不需要继承QLabel重绘,更简单:

QPixmap getRoundedPixmap(const QPixmap &srcPixmap, const int &radius, const int &width, const int &height)
{// 目标图片尺寸QSize desSize(width, height);// 新建一个目标大小的画布QpixmapQPixmap desPixMap(desSize);// 填充透明色作为背景desPixMap.fill(Qt::transparent);//以QPixmap 为绘画背景进行画笔绘制QPainter painter(&desPixMap);painter.setRenderHints(QPainter::Antialiasing); //抗锯齿painter.setRenderHints(QPainter::SmoothPixmapTransform); //平滑像素图变换QPainterPath path;//绘制路径//绘制圆角矩形,其中最后两个参数值的范围为(0-99),就是圆角的px值path.addRoundedRect(0, 0, desSize.width(), desSize.height(), radius, radius);// 将绘制的圆角矩形路径中内容进行裁剪painter.setClipPath(path);//将图片绘制到desPixmap中,IgnoreAspectRatio忽视图片比例painter.drawPixmap(0, 0, desSize.width(), desSize.height(), srcPixmap.scaled(desSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));painter.setClipping(false); // 关闭裁剪return desPixMap;
}

注意:此种方法不建议用于上面的PaintEvent绘制事件中绘制,因为它比上面的方法多一次拷贝QPixmap图片,我感觉会影响效率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2775048.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

WifiConfigStore初始化读取-Android13

WifiConfigStore初始化读取 1、StoreData创建并注册2、WifiConfigStore读取2.1 文件读取流程2.2 时序图2.3 日志 1、StoreData创建并注册 packages/modules/Wifi/service/java/com/android/server/wifi/WifiConfigManager.java mWifiConfigStore.registerStoreData(mNetworkL…

pytorch入门第一天

今天作为入门pytorch的第一天。打算记录每天学习pytorch的一些理解和笔记&#xff0c;以用来后面回顾。当然如果能帮到和我一样的初学者&#xff0c;那也是不胜荣幸。作为一名初学者&#xff0c;难免有些地方会现错误&#xff0c;欢迎各位大佬指出 预备知识 这里主要介绍pyto…

面向对象的三大特征之一继承

继承 继承的特性 概念&#xff1a;可以使得子类具有父类的属性(成员变量)和方法(成员方法)&#xff0c;还可以在子类中重新定义&#xff0c;追加属性和方法。 继承的格式&#xff1a; public class 子类名 extends 父类名{} 父类&#xff1a;基类、超类 子类&#xff1a;派生…

React + SpringBoot + Minio实现文件的预览

思路&#xff1a;后端提供接口&#xff0c;从minio获取文件的预览链接&#xff0c;返回给前端&#xff0c;前端使用组件进行渲染展示 这里我从minio获取文件预览地址用到了一个最近刚开源的项目&#xff0c;挺好用的&#xff0c;大伙可以试试&#xff0c;用法也很简单 官网&am…

C语言笔试题之实现C库函数 pow()(递归的思想)

实例要求&#xff1a; 1、请你实现C库函数 pow()&#xff08;stdio.h & math.h&#xff09; &#xff0c;即计算 x 的整数 n 次幂函数&#xff08;即x^n &#xff09;&#xff1b;2、函数声明&#xff1a;double myPow(double x, int n)&#xff1b;参数&#xff1a;1、x …

C++进阶(十三)异常

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、C语言传统的处理错误的方式二、C异常概念三、异常的使用1、异常的抛出和捕获2、异常的重新…

leetcode707. 设计链表

leetcode707. 设计链表 题目 思路 1.使用虚头节点&#xff0c;模拟class的初始化 2.class中添加一个链表长度的属性&#xff0c;便于后续操作 代码 class ListNode:def __init__(self, val0, nextNone):self.val valself.next nextclass MyLinkedList:def __init__(self)…

创新指南|生成式AI实验 - 企业快速渐进采用人工智能的科学新方法

生成式人工智能&#xff08;Gen AI&#xff09;正迅速成为各行各业的企业创新焦点。 生成式AI实验对于企业创新而言至关重要&#xff0c;不仅可以帮助企业识别最适合和最有影响的应用场景&#xff0c;还能促进组织沿着生成式 AI 学习曲线前进&#xff0c;建立早期的创新领导者和…

Elementplus报错 [ElOnlyChild] no valid child node found

报错描述&#xff1a;ElementPlusError: [ElOnlyChild] no valid child node found 问题复现&#xff08;随机例子&#xff09;&#xff1a; <el-popover placement"right" :width"400" trigger"click"><template #reference><e…

零基础学Python之Unitest模块

1.unittest简介及入门案例 &#xff08;1&#xff09;什么是Unitest Unittest是Python自带的单元测试框架&#xff0c;不仅适用于单元测试&#xff0c;还可用于Web、Appium、接口自动化测试用例的开发与执行。该测试框架可组织执行测试用例&#xff0c;并且提供丰富的断言方法…

Unity引擎学习笔记之【动画层操作】

动画层Animation Layer 一、动画器的三个基本状态 1. Any State&#xff08;任意状态&#xff09; “Any State”&#xff08;任意状态&#xff09;&#xff1a;这个状态可以用来连接多个状态机的任意状态转换。在动画控制器中&#xff0c;你可以使用“Any State”作为过渡条…

问题:银行账号建立以后,一般需要维护哪些设置,不包括() #学习方法#经验分享

问题&#xff1a;银行账号建立以后&#xff0c;一般需要维护哪些设置&#xff0c;不包括&#xff08;&#xff09; A&#xff0e;维护结算科目对照 B&#xff0e;期初余额初始化刷 C&#xff0e;自定义转账定义 D&#xff0e;对账单初始化 参考答案如图所示

c入门第十篇——指针入门

一句话来说: 指针就是存储了内存地址值的变量。 在前面讨论传值和传址的时候&#xff0c;我们就已经开始使用了指针来传递地址。 在正式介绍指针之前&#xff0c;我们先来简单了解一下内存。内存可以简单的理解为一排连续的房子的街道&#xff0c;每个房子都有自己的地址&#…

94.网游逆向分析与插件开发-游戏窗口化助手-地图数据获取的逆向分析与C++代码还原

内容参考于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;升级经验数据获取的逆向分析 码云地址&#xff08;游戏窗口化助手 分支&#xff09;&#xff1a;https://gitee.com/dye_your_fingers/sro_-ex.git 码云版本号&#xff1a;c4351a5b346d8953a1a8e3ec…

还是蓝海项目?浅谈steam海外道具搬运项目几个常见问题!

做steam这个项目做了已经3年多了。记得刚开始做的时候还是一个很冷门的项目&#xff0c;现在越来越多的朋友也开始了解这个项目。 其中不乏很多已经在别的地方了解过后来找我咨询的朋友。我发现一些同行或者说自媒体太过于虚假宣传&#xff0c;把steam这个项目说的太好了。也有…

Java学习15-- 面向对象学习3. 对象的创建分析【★】

&#xff08;本章看不懂多读几遍&#xff0c;弄懂后再往下章看&#xff09; 面向对象学习3. 对象的创建分析 Java Memory Structure: 如上图所示&#xff1a; 主要分为Stack和Heap Memory 其中Stack主要放method包括main 程序从main开始所以main最先进入Stack&#xff0c;等…

【十二】【C++】vector用法的探究

vector类创建对象 /*vector类创建对象*/ #if 1 #define _CRT_SECURE_NO_WARNINGS#include <iostream> using namespace std; #include <vector> #include <algorithm> #include <crtdbg.h>class Date {public:Date(int year 1900, int month 1, int …

Web课程学习笔记--CSS选择器的分类

CSS 选择器的分类 基本规则 通过 CSS 可以向文档中的一组元素类型应用某些规则 利用 CSS&#xff0c;可以创建易于修改和编辑的规则&#xff0c;且能很容易地将其应用到定义的所有文本元素 规则结构 每个规则都有两个基本部分&#xff1a;选择器和声明块&#xff1b;声明块由一…

【C++】引用与内联

个人主页 &#xff1a; zxctsclrjjjcph 文章封面来自&#xff1a;艺术家–贤海林 如有转载请先通知 文章目录 1. 前言2. 引用2.1 引用概念2.2 引用使用场景2.3 引用特性2.4 引用和指针的区别2.5 传值、传引用效率比较2.5.1 值和引用的作为返回值类型的性能比较 3. 内联函数3.1 …

Guava RateLimiter单机实战指南

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 Guava RateLimiter单机实战指南 前言maven坐标引入业务实现重要参数和方法关于warmupPeriod实战 前言 想象一下你是一位大厨&#xff0c;正在烹饪美味佳肴。突然之间&#xff0c;前来就餐的人潮如潮水…