写点什么

Qt|模仿文字浮动字母

  • 2022 年 7 月 23 日
  • 本文字数:2753 字

    阅读完需:约 9 分钟

前沿

最近可能是小视频着魔了,尤其是动画字幕效果的,身为一名技术开发人员,当然是想试一试了,哪怕只是简单的移动也是可以的~

这不,说干就干拿起来我的 C++语言就要尝试,还好使用的 Qt 框架,这样是使用 MFC 框架写小 demo,真的好困难呀!

先来看一看我实现的效果吧~



效果很简单就是文本向上移动,在移动过程中文字整体变大或缩小。

那么,我就来讲解下我是如何实现的吧!

功能实现

在实现这个文本移动的效果过程中,用到了以下几个功能:


1:定时器

2:QLabel 控件自绘

定时器操作

在 QWidget 中提供了一个定时器操作函数,我们只需要继承就可以实现了

virtual void timerEvent(QTimerEvent *event);
复制代码


使用 QWidget 自带的定时器操作时,就不需要 new QTiemr 的方式了,只需要使用 int 值记录当前开启定时器编号,等达到触发时间后进行处理即可。

文本偏移实现

首先在实现之前,先来讲解下主要流程是怎么回事吧!

1:定义文本移动定时器

2:每一秒触发一次,每次触发都需要创建一个新的控件用于展示内容。

3:触发后将已经展示的文本遍历方式向上整体偏移,偏移过程中会根据随机数,随机更改文本字体的大小。

4:字体变化,导致文本的宽度高度变更,用新的宽度、高度计算偏移后的位置。

在这里,我们可以对 QLabel 控件进行重绘,假设叫做 QCustomLabel,父类是 QLabel。那么我来一步一步地讲解我是如何实现定时器偏移的吧~

第一步

定义容器用于存储需要展示的文本内容,这里可以用一个简单的容器 vector 来记录,std::vector< std::string >m_vetContent;

第二步

定义容器用于存储已经展示过的文本控件,使用 QVector 来记录,QVector<QCustomLabel*> m_vetControls;


为什么第一步和第二步都是用 vector 记录,但是一个使用 C++的,另一个使用 Qt 的呢?


其实在第一步与第二步存储过程中,都可以使用 QVector 来进行记录,有一点需要注意的是,第二步存储必须使用 QVector。


为什么?因为 vector 与 QVector 存储都是先入先出的形式,我们在记录控件指针时,最先拿出的控件指针应该是后插入的数据。在 QVector 中从前端插入数据更为方便些,索性这两个步骤用的容器就稍微有一些差别了,你 get 到了吗?

第三步

触发定时器后,临时创建显示文本的控件数据,并及时存储到容器 m_vetControls 中,以防销毁窗口时不及时销毁指针导致的内存泄漏问题。


QCustomLabel *lab = new QCustomLabel(this);QSize size = lab->SetTextData(m_vetContent[m_nTimerTriggerNumber], 1);int nTop = (height() - size.height()) / 2;lab->setGeometry(DistanceLeft, nTop, size.width(), size.height());lab->show();m_vetControls.push_font(lab);
复制代码


使用 QVector 的 push_font()方法,每次存储的数据都最先展示,也就是将数据存储到下标为 0 的位置下。

第四步

数据存储后,更新所有展示的文本控件位置,这里使用:UpdateShowRectStyle()函数进行实现哦~


for (int i = 0; i < m_vetControls.size(); i++){  QCustomLabel *lab = m_vetControls[i];  QSize size = lab->UpdateZoomStyle(bFontZoom);  QRectF rectF = lab->geometry();  if (nTop == 0)  {    nTop = lab->geometry().top();  }  else  {    nTop = nTop - size.height();  }  lab->move(DistanceLeft, nTop);}this->update();
复制代码


循环遍历整个存储控件指针的数据内容,在更新位置的同时更改文本缩放大小(也就是变化字体大小),获取最新的变更位置,重新获取宽度、高度。


假设当前的高度是 0 时,说明是第一条数据需要变更,偏移的位置,直接是控件的高度;假设当前的高度非 0 时,说明是偏移过程中的某一条数据,因为是向上偏移,所有每次计算偏移后的高度时,都需要做减法,如果是向下偏移,每次计算偏移后的高度就是做加法了。

第五步

当读写完所有的显示内容时,停止定时器操作


if (m_nTimerTriggerNumber == m_vetContent.size()){  killTimer(m_nTimerId);  m_nTimerId = 0;}
复制代码


到这里,文字自动偏移的功能就实现了,接下来我们来讲一讲是如何自绘 QLabel 控件吧~

控件自绘

首先我们需要定义 QLabel 的自绘类,这里我给除了简单的框架,以后需要什么功能直接追加就可以啦~


.h 使用


#pragma once
#include <QLabel>
class QCustomLabel : public QLabel{ Q_OBJECT
public: QCustomLabel(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); ~QCustomLabel();};
复制代码


.cpp 使用


#include "QCustomLabel.h"QCustomLabel::QCustomLabel(QWidget *parent, Qt::WindowFlags f)  : QLabel(parent, f){}
QCustomLabel::~QCustomLabel(){}
复制代码


想要实现什么功能,就只需要在这个基础上扩充就可以了。


在自绘 QLabel 中有两个重点


1:如何根据字体的大小固定文本区域?


2:文字闪烁效果实现


根据这两个重点来绘制 QLable 控件吧!

功能 1:

字体的大小可以使用随机数 qrand()来实现。


使用方法:


QTime time = QTime::currentTime();qsrand(time.msec() + time.second() * 1000);int nFontSize = qrand() % 30 + 20;
复制代码


这种方式生成的随机数保证了唯一性。


根据字体大小,设置 QFont 的属性


QFont fontContent =this->font();//设置:字体样式:微软雅黑fontContent.setFamily("Microsoft YaHei");//设置:字体大小:22fontContent.setPixelSize(nFontSize);//字体绑定this->setFont(fontContent);
复制代码


重点来啦!!!


设置了字体风格之后,这时候我们是可以获取到字体的高度的,但是整体的宽度是获取不到的需要动态获取。


QFontMetrics metrics(font());int nheight = metrics.height();//设置内容并存储文本内容m_qsTextContent = QString::fromLocal8Bit(sText.c_str());setFixedHeight(nheight);this->setText(m_qsTextContent);this->adjustSize();int nwidth = this->width();//设置自定义QLable控件的宽度以及高度QSize size(nwidth , nheight);
//开启定时器m_nTimerId = startTimer(100);return size;
复制代码

功能 2:

文字颜色渐变展示。


这个功能很简单,核心就是实时的更新 QColor 值,这里我使用了随机数使每次生成的颜色值都不相同


QFontMetrics metrics(font());int x = 0;int y = (height() + metrics.ascent() - metrics.descent()) / 2;QColor color;for (int i = 0; i < m_qsTextContent.size(); i++){  //设置:色调(H)、饱和度(S)、亮度(Y)  int nIndex = (m_nStep + i) % 16;  color.setHsv((15 - nIndex) * 16, 255, 191);  painter->setPen(color);  //单个字符绘制  painter->drawText(x, y, QString(m_qsTextContent[i]));  //计算下一个字符的x坐标起始点  x += metrics.width(m_qsTextContent[i]);}
复制代码

总结

到这里,文字移动效果就已经实现了,功能比较简单,唯一的难点就在于文字风格变动时,区域的变化,只要我们了解了变化规律,位置展示还不是小菜一碟吗?


我是中国好公民 st,一名 C++开发程序媛~

发布于: 3 小时前阅读数: 11
用户头像

书山有路勤为径,学海无涯苦作舟 2022.07.01 加入

擅长语言:C++ 涉及语言:Python

评论

发布
暂无评论
Qt|模仿文字浮动字母_qt_中国好公民st_InfoQ写作社区