QT- label实现滚动字幕 (跑马灯)效果 -像素级

2023-05-16

QT-label滚动字幕

  • 原理
    • 代码
    • 完整源码 + 部件提升

想通过QSS实现更多效果的请搜索QT自带帮助文档 Qt Style Sheets Examples,使用样式表来定制程序界面

原理

在这里插入图片描述

让label字母滚动起来的原理很简单

Created with Raphaël 2.2.0 开始 是否超过this->with宽度 开启定时器,s秒增加一次位移值,调用绘画事件 重载绘画事件,根据位移值生成矩形,在不同位置的矩形上绘制文本 结束 正常显示文本,不滚动 yes no

所以就是这么一个过程:
1,判断字符串的像素宽度是否超过窗体宽度,超过则开启滚动 (主要是开启定时器)
2,定时器固定毫秒去修改位移值left,然后调用绘图事件
3,绘图事件根据left值,生成一个矩形(默认左上角为0,0),然后drawText根据矩形绘画文本。由于left一直在变动,于是矩形也在不停变动,生成的文本也在不停变动,就实现了滚动字幕。
***定时器用的是定时器事件,适合用来处理比较简单的重复任务,具体可以看这里


代码

根据上面的分解,整个流程就很清晰了,public继承QLabel,第一步判断可以先从setText开始

需要注意的是,必须要设置label的窗口最大值。因为是否滚动的关键是判断是否超出this->with,所以this->with不能变动,一变动那触发滚动的阈值也变动了。

//在设置文本、缩放事件两次调用自适应的函数
void label_scroll::setText(const QString &txt)
{
    if(Qt::mightBeRichText(txt))//判断是否为富文本 需要包含<QTextDocument>
        flag = 0;  //0不处理,直接用原本的绘画事件显示
    else
        flag = 1;

    QLabel::setText(txt);
    upateLabelRollingState();// 这个函数就是判断的核心
}

upateLabelRollingState();// 这个函数就是判断是否开启滚动的关键核心,计算文本像素长度和开启定时器

//用来判断label文本是否需要滚动起来,是这块功能的核心
void label_scroll::upateLabelRollingState()
{
    //获取文本大小,小于文本框长度,则无需滚动
    QFont ft = font();// 获取当前字体的格式,里面有文本大小和文本像素大小
    QFontMetrics fm(ft); // 以当前的字体格式为基础

    #if QT_VERSION > QT_VERSION_CHECK(5,11,0)//根据官方文档说明,5.11后使用新的函数
    text_wpixel = fm.horizontalAdvance(text() ); //以当前的字体格式为基础,计算字符串的像素宽度
    #else
    text_wpixel = fm.width(text() ); //同上,低于5.11使用此函数
    #endif

	// 长度超出本身label的像素大小,则开启滚动***关键判断
    if( (text_wpixel > this->width() ) && flag == 1 )
    {
        left = 0; // 清空像素滚动量

        #if QT_VERSION > QT_VERSION_CHECK(5,11,0)//根据官方文档说明,5.11后使用新的函数
        blank = " ";//空格
        blank_wp = fm.horizontalAdvance(blank );//空格的像素宽度,方便后面计算是否到达末尾
        #else
        blank = " ";//空格
        blank_wp = fm.width(blank );//空格的像素宽度
        #endif

        //开启定时器,定时器定时改变滚动量left
        timerId = startTimer(speedt);

    }
    else//关闭文本框滚动
    {
        flag = 0; //关闭
        if(timerId >= 0){
            killTimer(timerId);//关闭定时器
            timerId = -1;
        }
    }

}

开启定时器之后,重载定时器事件timerEvent,负责按时修改位移值left

//定时改位移量,到末尾时改为开头  负责修改当前像素位移值
void label_scroll::timerEvent(QTimerEvent *e)
{
    if(e->timerId() == timerId && isVisible())
    {
        left += spixel;// 每次增加对应像素
        if((left + 20) > (text_wpixel + blank_wp) )// 判断当前宽度是否超过字符串的总宽度,代表到末尾了
            left = 1-( this->width() ); //重新添加,负数代表从最右边开始

        //repaint();//立即触发一次刷新,不会产生冗余,但是耗性能
        update();//不会立马刷新,有可能产生事件冗余,但是节省性能      
        //update和repaint的具体区别,请看QT文档说明
    }

    QLabel::timerEvent(e); // 如果没有进去上面那个滚动判断,则执行默认操作
}

重载绘图事件,根据timerEvent修改的位移值left绘制矩形,再根据矩形位置绘画字符串

//重绘事件,根据位移量left显示文本
void label_scroll::paintEvent(QPaintEvent *e)
{
    if(flag == 0){ // 不处理,直接调用标签的默认函数,适配一般情况
        QLabel::paintEvent(e);
        return;
    }

    QPainter pen(this);
    
    //  获取当前label的矩形大小
    QRect rc = rect();
    rc.setHeight(rc.height() );
    rc.setWidth(rc.width() );

    QString strText = blank + text();// 组合完整文本
    //修改矩形x轴, 由于left在不断变大,setLeft就在不断变小,(0,0)在左上角,固左移
    rc.setLeft(rc.left() - left); 
    
    pen.drawText(rc,Qt::AlignVCenter, strText);//根据给定的矩形坐标,绘制文本
}

完整源码 + 部件提升

.h文件

#ifndef LABEL_SCROLL_H
#define LABEL_SCROLL_H


#include <QDebug>
#include <QLabel>
#include <QTimerEvent>
#include <QPaintEvent>
#include <QTextDocument> //判断富文本用的
#include <QPainter>

// 继承于标签,之后在qt设计师内右键选择"提升" 使得这个继承类控制对应需要滚动的标签
// https://www.kanzhun.com/jiaocheng/517505.html
class label_scroll :public QLabel
{
    Q_OBJECT
public:
    explicit label_scroll(QWidget *parent = nullptr);
    ~label_scroll();

    //自适应函数,判断label文本是否需要滚动起来
    void upateLabelRollingState();

public slots:
    //定时改位移量,到末尾时改为开头  负责修改当前像素位移值left  startTimer开始,killTimer结束
    void timerEvent(QTimerEvent *e) Q_DECL_OVERRIDE;

    //重绘事件,根据位移量left显示文本
    void paintEvent(QPaintEvent *e) Q_DECL_OVERRIDE;

    //在设置文本、缩放事件两次调用自适应的函数
    void setText(const QString &txt);

    //设置图片,主要把lt设回0,使其恢复正常的图片显示
    void setPixmap(const QPixmap &pix);

    //窗口变化事件
    void resizeEvent(QResizeEvent *e) Q_DECL_OVERRIDE;

    // 根据给定的数值,修改滚动速度 sp是一次滚动多少像素,st是多少秒触发一次滚动
    void setspeed(int sp=10,int st=300);

private:
    int timerId; //定时器id
    int text_wpixel; //储存的当前label内字符串的像素水平长度

    int speedt;// 多久触发一次滚动
    int spixel;// 一次滚动多少像素

    int left;// 标明当前的像素滚动量

    QString blank;//空格
    int blank_wp;//空格的像素宽度

    int start_scroll;

    uint8_t flag; //判断是否应该开启滚动 0否 1真
};

#endif // LABEL_SCROLL_H

.cpp文件

#include "label_scroll.h"

label_scroll::label_scroll(QWidget *parent):QLabel(parent)
{
    timerId = -1;// 定时器的ID
    text_wpixel = 0; //文本的像素长度

    speedt = 80;// 多久触发一次滚动
    spixel = 10;// 一次滚动多少像素

    //start_scroll = this->width();//保存了窗体最初的宽度,避免窗体变动就不滚动

    flag = 0;//默认不处理
}

label_scroll::~label_scroll()
{
    if(timerId >= 0)
        killTimer(timerId);
}

//在设置文本、缩放事件两次调用自适应的函数
void label_scroll::setText(const QString &txt)
{
    if(Qt::mightBeRichText(txt))//判断是否为富文本
        flag = 0;  //0不处理,直接用原本的绘画事件显示,当属于富文本时使用这个 1左到右 2上到下
    else
        flag = 1;

    QLabel::setText(txt);
    upateLabelRollingState();
}

//设置图片,主要把lt设回0,使其恢复正常的图片显示
void label_scroll::setPixmap(const QPixmap &pix)
{
    flag=0;
    QLabel::setPixmap(pix);
}

//窗口变化事件
void label_scroll::resizeEvent(QResizeEvent *e)
{
    QLabel::resizeEvent(e);
    upateLabelRollingState();
}

// 根据给定的数值,修改滚动速度  sp是一次滚动多少像素,st是多少秒触发一次滚动
void label_scroll::setspeed(int sp,int st)
{
    spixel = sp;
    speedt = st;

    upateLabelRollingState(); // 刷新一次滚动量
}

//用来判断label文本是否需要滚动起来,是这块功能的核心
void label_scroll::upateLabelRollingState()
{
    //获取文本大小,小于文本框长度,则无需滚动
    QFont ft = font();// 获取当前字体的格式,里面有文本大小和文本像素大小
    QFontMetrics fm(ft); // 以当前的字体格式为基础

    #if QT_VERSION > QT_VERSION_CHECK(5,11,0)//根据官方文档说明,5.11后使用新的函数
    text_wpixel = fm.horizontalAdvance(text() ); //以当前的字体格式为基础,计算字体的像素宽度
    #else
    text_wpixel = fm.width(text() ); //以当前的字体格式为基础,计算字体的像素宽度
    #endif

    if( (text_wpixel > this->width() ) && flag == 1 )// **长度或高度超出本身label的像素大小,则开启滚动***关键判断
    {
        left = 0; // 标志当前的像素滚动量

        #if QT_VERSION > QT_VERSION_CHECK(5,11,0)//根据官方文档说明,5.11后使用新的函数
        blank = " ";//空格
        blank_wp = fm.horizontalAdvance(blank );//空格的像素宽度,方便后面计算是否到达末尾
        #else
        blank = " ";//空格
        blank_wp = fm.width(blank );//空格的像素宽度
        #endif

        qDebug()<< "OK!";

        //开启定时器,定时器定时触发滚动效果
        timerId = startTimer(speedt);

    }
    else//关闭文本框滚动
    {
        qDebug()<< "no OK!";
        flag = 0; //关闭
        if(timerId >= 0){
            killTimer(timerId);
            timerId = -1;
        }
    }

}

//定时改位移量,到末尾时改为开头  负责修改当前像素位移值
void label_scroll::timerEvent(QTimerEvent *e)
{
    if(e->timerId() == timerId && isVisible())
    {
        left += spixel;// (0,0)在左上角,每次增加对应像素
        if((left + 20) > (text_wpixel + blank_wp) )// 表示到末尾了
            left = 1-( this->width() ); //重新添加,负数代表从最右边开始

        //repaint();//立即触发一次刷新,不会产生冗余,但是耗性能
        update();//不会立马刷新,有可能产生事件冗余,但是节省性能      
        //update和repaint的区别,请看QT文档说明
    }

    QLabel::timerEvent(e);
}

//重绘事件,根据位移量left显示文本
void label_scroll::paintEvent(QPaintEvent *e)
{
    if(flag == 0){ // 不处理,直接调用标签的默认函数
        QLabel::paintEvent(e);
        return;
    }

    QPainter pen(this);
    //  获取当前label的矩形大小
    QRect rc = rect();
    rc.setHeight(rc.height() /*- 2*/);
    rc.setWidth(rc.width() /*- 2*/);

    QString strText = blank + text();
    rc.setLeft(rc.left() - left); //修改矩形 x轴, 由于left在不断变大,setLeft就在不断变小,(0,0)在左上角,固左移
    pen.drawText(rc,Qt::AlignVCenter, strText);//根据给定的矩形坐标,绘制标签
}

然后在UI设计师里面提升一下需要滚动的label部件即可
在这里插入图片描述


参考文章

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

QT- label实现滚动字幕 (跑马灯)效果 -像素级 的相关文章

随机推荐

  • maven-assembly-plugin插件的使用方法

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 一 Assembly 是什么意思 xff1f 二 maven assembly plugin是什么 xff1f 1 它是maven中针对打包任务而提供的标准插件 三 mav
  • DLL编辑和源码管理的一些疑问和见解

    xff08 本来不想放在首页的 xff0c 但是因为的确需要帮助 xff0c 姑且放在首页希望对本文描述到的问题有见解告诉小弟一声 xff09 今天因为类库里面有一个地方写错了 xff0c 所以找经理要了类库的源码 xff0c 经理说我用的
  • Unity3D--学习太空射击游戏制作(四)

    步骤七 xff1a 添加声音和特效 射击声音和爆炸效果 01 xff1a 在Project窗口单机右键 xff0c 选择Import Package gt Custome Package 然后到资源文件目录packages浏览unity包文
  • pnfs加密aes部分。

    首先需要找到加密的地方 实际上 xff0c 文件系统的读写 xff0c 可以首先查看vfs write amp vfs read 然后根据具体定义的 file operations 查找 xff0c 对应的文件系统的read和write函数
  • Ubuntu使任何用户都有设置图形网络权限的方法

    sudo vi usr share polkit 1 actions org freedesktop NetworkManager policy 695行 lt lt allow active gt auth admin keep lt a
  • Ajax 跨域请求 Access-Control-Allow-Origin 问题

    这转移一台GMtool的服务器 xff0c 结果转移过去后 xff0c 去登陆账号密码卡在登陆界面上 xff0c 用google开发者工作查看network时 xff0c 是卡在一个验证的服务器上 xff0c 然而可悲的是那台验证上的服务也
  • 国家气象局免费天气预报接口,城市代码(JSON格式)

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 原文链接 xff1a blog csdn net zgyulongfei 国家气象局提供免费的天气预报接口 xff0c 但是访问时候需要指定城市代码 update 2015
  • AutoCAD2016简体中文破解版32位64位下载

    AutoCAD2016序列号 xff1a 666 69696969 667 98989898 400 45454545 066 66666666 任意一个 AutoCAD2016产品密钥 xff1a 001H1 AutoCAD2016软件3
  • 树莓派进阶之路 (031) -字符问题(1) - GBK汉字编码表(转)

    转载 xff1a http blog sina com cn s blog 8184e033010109ug html 基本简介 GB码 xff0c 全称是GB2312 80 信息交换用汉字编码字符集基本集 xff0c 1980年发布 xf
  • 外贸盒子x96max+ 搭建Armbian系统 (附国内可用的img镜像下载地址)

    记录一下在x96max 43 外贸盒子上面搭建Armbian的历程 Armbian是什么操作过程 救砖历程 xff1a 国内外相关电视盒子论坛 Armbian是什么 Armbian是轻量级的Debian系统 xff0c 为ARM开发板专门发
  • 手机上输入http://192.168.1.102:8888/FiddlerRoot.cer为什么下载不了证书

    因为之前你的手机可能已经安装了该证书 xff0c 所以再次下载会说找不到证书 解决办法 如果你遇到上面的问题 就可能是证书的问题 我的本地证书是用系统生成证书的一个软件生成的个人证书 所以出现了问题 操作步骤如下 1 将之前的证书删除打开系
  • 区块链上编程:DApp 开发实战——来写个竞猜游戏吧!

    本文旨在引导对 DApp 开发感兴趣的开发者 xff0c 构建一个基于以太坊去中心化应用 xff0c 通过开发一款功能完备的竞猜游戏 xff0c 迈出 DApp 开发的第一步 xff0c 通过实例讲解 Solidity 语言的常用语法 xf
  • pip更改下载源设置

    任何一个信息都可以把人分为两类 xff0c 知道的和不知道的 有些我们已知的信息 xff0c 自己觉得很平常 xff0c 却可能对另一些不知道的人来说很有用处 比如今天要说的这个小技巧 xff0c 我自己原以为不值一提 xff0c 网上也很
  • 让div在屏幕中居中(水平居中+垂直居中)的几种方法

    水平居中方法 1 inline xff0c inline block元素的水平居中 xff0c 在父级块级元素中设置text align center 2 确定宽度的块级元素水平居中方法 margin xff1a 0 auto xff1b
  • 从ELK到EFK

    背景 作为中国最大的在线教育站点 xff0c 目前沪江日志服务的用户包含沪江网校 xff0c 交易 xff0c 金融 xff0c CCtalk xff08 直播平台 xff09 等多个部门的多个产品的日志搜索分析业务 xff0c 每日产生的
  • 证明:实对称矩阵中,属于不同特征值的特征向量相互正交

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 证明 xff1a 实对称矩阵中 xff0c 属于不同特征值的特征向量相互正交 设AP 61 1P xff0c AP 61 2P xff0c 其中A为实对称矩阵 xff0c
  • 宝塔面板一键docker部署

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 推荐 xff1a 宝塔面板一键docker部署 0 购买服务器 1 安装docker root 64 VM 0 2 centos curl fsSL https get d
  • 异步I/O Asynchronous I/O

    原帖地址 xff1a http www ibm com developerworks cn linux l async AIO 简介 Linux 异步 I O 是 Linux 内核中提供的一个相当新的增强 它是 2 6 版本内核的一个标准特
  • Trapping Rain Water II

    Given n x m non negative integers representing an elevation map 2d where the area of each cell is 1 x 1 compute how much
  • QT- label实现滚动字幕 (跑马灯)效果 -像素级

    QT label滚动字幕 原理代码完整源码 43 部件提升 想通过QSS实现更多效果的请搜索QT自带帮助文档 Qt Style Sheets Examples xff0c 使用样式表来定制程序界面 原理 让label字母滚动起来的原理很简单