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

news2024/11/15 10:15:24

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

    // 新建一个目标大小的画布Qpixmap
    QPixmap 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://www.coloradmin.cn/o/1440659.html

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

相关文章

Vue3.0(五):Vue-Router 4.x详解

Vue-Router详解 vue-router教程 认识前端路由 路由实际上是网络工程中的一个术语 在架构一个网络的时候&#xff0c;常用到两个很重要的设备—路由器和交换机路由器实际上就是分配ip地址&#xff0c;并且维护着ip地址与电脑mac地址的映射关系通过映射关系&#xff0c;路由器…

【Godot4.2】文件系统自定义控件 - GroupButtons

GroupButtons 概述 读者朋友们好&#xff0c;我是巽星石&#xff0c;这是我的Godot4.2文件系统自定义控件系列文章。 在很多程序或插件设计中&#xff0c;都会用到一堆按钮的形式&#xff0c;好处是比较直观&#xff0c;用啥点啥&#xff0c;本质上相当于一个简化的二级树形…

【Git版本控制 01】基本操作

目录 一、初始配置 二、添加文件 三、查看日志 四、修改文件 五、版本回退 六、撤销修改 七、删除文件 一、初始配置 Git版本控制器&#xff1a;记录每次的修改以及版本迭代的一个管理系统。 # 初始化本地仓库&#xff1a;git init(base) [rootlocalhost gitcode]# gi…

【通讯录案例-偏好设置 Objective-C语言】

一、刚才,我们plist存储,讲完了,这个plist,我直接,右键,打开 打开 不用xcode,我就用文本文档打开,打开方式:其他 选择:文本编辑 打开 好,这个里边儿啊,就是我们刚才存的一个Key:Value 它本质上,是一个xml 这是一种文件的格式, 等你们讲到网络的时候,实际上,…

Android 环境搭建

1、桥接工具安装 网站地址&#xff1a;AndroidDevTools - Android开发工具 Android SDK下载 Android Studio下载 Gradle下载 SDK Tools下载 使用安装包&#xff1a; adb 查看当前链接成功的设备&#xff1a;adb devices 使用adb shell指令来进入到手机的后台&#xff1a;

Ondo宣布将其原生稳定币USDY带入Sui生态

重要提示&#xff1a;USDY是由短期美国国债支持的token化票据&#xff0c;持有者享受稳定币的实用性同时获得收益。USDY不得在美国或向美国人出售或以其他方式提供。USDY也未根据1933年美国证券法注册。 不到一年的时间&#xff0c;Sui已经成为全链TVL排名前十的区块链&#xf…

MySQL- 运维-分库分表-Mycat

一、Mycat概述 1、安装 2、概念介绍 二、Mycat入门 启动服务 三、Mycat配置 1、schema.xml 2、rule.xml 3、server.xml 四、Mycat分片 1、垂直分库 2、水平分表 五、Mycat管理及监控 1、Mycat原理 2、Mycat管理工具 &#xff08;1&#xff09;、命令行 &#xff08;2&#…

SpringBoot + Tess4J 实现本地与远程图片的文字识别

1 前言 1.1 概要 在本文中&#xff0c;我们将探讨如何在Spring Boot应用程序里集成Tess4J来实现OCR&#xff08;光学字符识别&#xff09;&#xff0c;以识别出本地和远程图片中的文字。 我们将从添加依赖说起&#xff0c;然后创建服务类以实现OCR&#xff0c;最后展示如何处…

基于微信小程序的新生报到系统的研究与实现,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

如何给闲置电脑安装黑群晖

准备 diskgenius &#xff0c;黑群晖引导文件&#xff08;有些需要扩展驱动包&#xff09;&#xff0c;如果给U盘安装需要balenaEtcher或者rufus&#xff08;U盘安装还需要ChipGenus&#xff09;&#xff0c;如果给硬盘安装需要有pe推荐firePE或U启通 我以U盘为例 首先去找这…

【RPA】浅谈RPA技术及其应用

摘要&#xff1a;随着信息技术的飞速发展&#xff0c;企业对于自动化、智能化的需求日益增强。RPA&#xff08;Robotic Process Automation&#xff0c;机器人流程自动化&#xff09;技术应运而生&#xff0c;为企业提供了全新的自动化解决方案。本文首先介绍了RPA技术的基本概…

Stability AI一种新型随心所欲生成不同音调、口音、语气的文本到语音(TTS)音频模型

该模型无需提前录制人声样本作为参考&#xff0c;仅凭文字描述就能生成所需的声音特征。用户只需描述他们想要的声音特点&#xff0c;例如“一个语速较快、带有英国口音的女声”&#xff0c;模型即可相应地生成符合要求的语音。它不仅能模仿已有的声音&#xff0c;还能根据用户…

ESP8266 tcpsocket透传模式流程介绍

一、整体流程介绍 二、固件介绍 固件视频演示地址&#xff1a; ESP8266-配网&热点设置说明_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1hq4y127dN/?spm_id_from333.999.0.0

第三百一十五回

文章目录 1. 概念介绍2. 基本用法3. 补充用法4. 内容总结 我们在上一章回中介绍了"再谈ListView中的分隔线"&#xff0c;本章回中将介绍showMenu的用法.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在第一百六十三回中介绍了showMenu相关的内容…

Log4j2漏洞(二)3种方式复现反弹shell

★★免责声明★★ 文章中涉及的程序(方法)可能带有攻击性&#xff0c;仅供安全研究与学习之用&#xff0c;读者将信息做其他用途&#xff0c;由Ta承担全部法律及连带责任&#xff0c;文章作者不承担任何法律及连带责任。 1、前言 明天就是除夕了&#xff0c;提前祝大家&#x…

Apollo

一. 部署说明 apollo配置中心由三个组件组成&#xff1a; ConfigService 配置中心&#xff0c;客户端从这个服务拉配置&#xff0c;同时内置了Eureka、MetaService。每个环境要有一个 AdminService 配置管理服务&#xff0c;管理数据库配置&#xff0c;Portal调这个服务修改、…

解决端口被占用问题

写文章原因: 本人在安装alist的时候,在使用5244端口的时候,显示端口被占用,于是想查看一下端口是被什么程序占用了,是否可以杀死占用的程序,还是更换端口. failed to start http: listen tcp 0.0.0.0:5244: bind: Only one usage of each socket address (protocol/network a…

专业140+总分420+华中科技大学824信号与系统考研经验电子信息与通信工程,真题,大纲,参考书。

今年考研分数自己感觉还是比较满意&#xff0c;专业824信号与系统考的最好140&#xff0c;总分420&#xff0c;如愿上岸华科&#xff0c;回顾自己的这一年的复习&#xff0c;总结一些自己的经验&#xff0c;希望对报考华科的同学有帮助。 专业课&#xff1a; 824信号与系统在…

如何构建一个高效的微服务治理闭环管理体系

随着企业业务的快速发展和数字化转型的推进&#xff0c;微服务架构因其高度的灵活性、可扩展性和可维护性而逐渐成为主流。然而&#xff0c;微服务架构的复杂性也带来了诸多治理挑战。为了有效应对这些挑战&#xff0c;构建一个微服务治理闭环至关重要。 1、微服务治理概述 微…

SpringCloud-Ribbon:负载均衡(基于客户端)

6. Ribbon&#xff1a;负载均衡(基于客户端) 6.1 负载均衡以及Ribbon Ribbon是什么&#xff1f; Spring Cloud Ribbon 是基于Netflix Ribbon 实现的一套客户端负载均衡的工具。简单的说&#xff0c;Ribbon 是 Netflix 发布的开源项目&#xff0c;主要功能是提供客户端的软件负…