QT-label滚动字幕

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

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

原理

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

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

所以就是这么一个过程:
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不处理,直接用原本的绘画事件显示elseflag = 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() ); //以当前的字体格式为基础,计算字符串的像素宽度#elsetext_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 );//空格的像素宽度,方便后面计算是否到达末尾#elseblank = " ";//空格blank_wp = fm.width(blank );//空格的像素宽度#endif//开启定时器,定时器定时改变滚动量lefttimerId = 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; //定时器idint 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;// 定时器的IDtext_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上到下elseflag = 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() ); //以当前的字体格式为基础,计算字体的像素宽度#elsetext_wpixel = fm.width(text() ); //以当前的字体格式为基础,计算字体的像素宽度#endifif( (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 );//空格的像素宽度,方便后面计算是否到达末尾#elseblank = " ";//空格blank_wp = fm.width(blank );//空格的像素宽度#endifqDebug()<< "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部件即可


参考文章

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

  1. html网页内容自动滚动实现跑马灯效果

    1.效果1 超出div高度,文本自动滚动(像跑马灯一样从下往上滚动) 一个div里面有文字 1.如果文字没超出div高度:文字不用滚动 2.如果文字太多超出了div高度,那些文字就自动滚动 ps:滚动 ...

  2. vue实现分组轮播(一排放4个小的、无缝滚动、跑马灯效果)

    前段时间写了个无缝滚动轮播图,有小伙伴评论说,想要一行放几个小的应该怎么实现,现在他来了,在原有无缝滚动轮播图的基础上,小小改动便能实现需求,纯vue不依赖任何第三方插件,复制粘贴即刻使用,话不多说, ...

  3. WPF中DataGrid自动滚动,跑马灯效果实现

    前端: <DataGrid x:Name="dg" AutoGenerateColumns="False" ><DataGrid.Column ...

  4. TextView跑马灯效果

    转载:http://www.2cto.com/kf/201409/330658.html 一.只想让TextView显示一行,但是文字超过TextView的长度怎么办? 在开头显示省略号 androi ...

  5. Android开发 实现跑马灯效果滚动字幕

    Android开发 实现跑马灯效果滚动字幕 ~! ~ !~ 浙江温州!~ 浙江温州!~江南皮革厂倒闭了! 黄鹤老板欠下了3.5个亿 ! 带着他的小姨子跑了! 我们没有办法 没有办法,拿着钱包抵工资, ...

  6. Qt工作笔记-跑马灯效果

    逻辑: 使用静态变量确定位置: 利用QString中mid这函数的性质: 程序运行截图如下: 代码如下: widget.h #ifndef WIDGET_H #define WIDGET_H#incl ...

  7. iOS - 支持水平 / 垂直显示自动滚动的跑马灯控件 --- SKAutoScrollLabel 的使用和实现

    原文链接:http://www.jianshu.com/p/7221bc08f26a SKAutoScrollLabel 是一个同时支持水平 / 垂直两种类型的 "跑马灯" 效果的 ...

  8. c语言小程序跑马灯,微信小程序实现跑马灯效果(完整代码)

    在微信小程序 里实现跑马灯效果,类似滚动字幕或者滚动广告之类的,使用简单的CSS样式控制,没用到JS,效果如下图: Wxml代码:一个人活着就是为了让更多的人更好的活着! Wxss代码:/*首页跑马灯 ...

  9. web展现mysql_web页面实现LED跑马灯效果(涉及web前端、原生JS、PHP、mysql)

    本帖最后由 yoin 于 2019-11-21 16:24 编辑 产品需求: LED跑马灯页面展示内容(班级电脑展示) setLED更改内容(老师电脑更改内容) LED页面及时更新内容设计思路: 最初 ...

最新文章

  1. 入门 Python GUI 开发的第一个坑
  2. 当AI实现多任务学习,它究竟能做什么?
  3. 查找字符位置_查找某个字符最后一次出现的位置
  4. CSS height:100%无效
  5. springmvc登路示例(注解)
  6. oracle rman恢复表空间,Oracle数据库RMAN恢复之表空间和数据块介质的恢复
  7. bootstarp table
  8. matlab 读取照片imread,利用matlab读取图像
  9. python计算相关性显著性p值_基于python实现计算两组数据P值
  10. routing zuul_金三银四跳槽季快到了:送上Spring cloud全家桶系列之Zuul
  11. 滴滴 App 强制调取用户通讯录;子弹短信仍能泄露信息;特朗普炮轰谷歌 | 极客头条...
  12. linux中如何解决文件已删除但空间不释放的案例
  13. k8s 1.16安装metrics server
  14. mysql concat函数进行模糊查询
  15. Java常见算法(一)
  16. java上传图片至阿里云oss服务器
  17. CentOS7下使用vlmcsd搭建KMS服务器激活环境
  18. np.random用法
  19. Python之(scikit-learn)机器学习
  20. Go项目配置管理神器之viper使用详解

热门文章

  1. python科研用哪个软件_科研画图都用什么软件?
  2. [SMOJ2095]Bug2
  3. Linux驱动开发-proc接口介绍
  4. golang flow工作流引擎-自己挖坑自己填
  5. Weex 的采坑指南
  6. python抓取微博数据_Python爬虫实现半自动发微博
  7. PostgreSQL + Postgis
  8. 收银管理系统多少钱一套?去哪里买比较靠谱?
  9. 科技版“传音入密”:音频聚光灯现在怎么样了?
  10. 神(gai)奇(si)的MIUI优化