• 使用Qt模仿文字浮动字母


    目录

    前沿

    功能实现

    定时器操作

    文本偏移实现

    第一步

    第二步

    第三步

    第四步

    第五步

    控件自绘

    功能1:

    功能2:

    总结


    前沿

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

    这不,说干就干拿起来我的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 m_vetControls;

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

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

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

    第三步

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

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

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

    第四步

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

    1. for (int i = 0; i < m_vetControls.size(); i++)
    2. {
    3. QCustomLabel *lab = m_vetControls[i];
    4. QSize size = lab->UpdateZoomStyle(bFontZoom);
    5. QRectF rectF = lab->geometry();
    6. if (nTop == 0)
    7. {
    8. nTop = lab->geometry().top();
    9. }
    10. else
    11. {
    12. nTop = nTop - size.height();
    13. }
    14. lab->move(DistanceLeft, nTop);
    15. }
    16. this->update();

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

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

    第五步

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

    1. if (m_nTimerTriggerNumber == m_vetContent.size())
    2. {
    3. killTimer(m_nTimerId);
    4. m_nTimerId = 0;
    5. }

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

    控件自绘

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

    .h 使用

    1. #pragma once
    2. #include
    3. class QCustomLabel : public QLabel
    4. {
    5. Q_OBJECT
    6. public:
    7. QCustomLabel(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
    8. ~QCustomLabel();
    9. };

    .cpp 使用

    1. #include "QCustomLabel.h"
    2. QCustomLabel::QCustomLabel(QWidget *parent, Qt::WindowFlags f)
    3. : QLabel(parent, f)
    4. {
    5. }
    6. QCustomLabel::~QCustomLabel()
    7. {
    8. }

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

    在自绘QLabel中有两个重点

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

    2:文字闪烁效果实现

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

    功能1:

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

    使用方法:

    1. QTime time = QTime::currentTime();
    2. qsrand(time.msec() + time.second() * 1000);
    3. int nFontSize = qrand() % 30 + 20;

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

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

    1. QFont fontContent =this->font();
    2. //设置:字体样式:微软雅黑
    3. fontContent.setFamily("Microsoft YaHei");
    4. //设置:字体大小:22
    5. fontContent.setPixelSize(nFontSize);
    6. //字体绑定
    7. this->setFont(fontContent);

    重点来啦!!!

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

    1. QFontMetrics metrics(font());
    2. int nheight = metrics.height();
    3. //设置内容并存储文本内容
    4. m_qsTextContent = QString::fromLocal8Bit(sText.c_str());
    5. setFixedHeight(nheight);
    6. this->setText(m_qsTextContent);
    7. this->adjustSize();
    8. int nwidth = this->width();
    9. //设置自定义QLable控件的宽度以及高度
    10. QSize size(nwidth , nheight);
    11. //开启定时器
    12. m_nTimerId = startTimer(100);
    13. return size;

    功能2:

    文字颜色渐变展示。

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

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

    总结

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

    我是中国好公民,专注C++开发程序猿~

  • 相关阅读:
    Eureka详解
    03 基础配置webpack3打包vue文件
    基于matlab的神经网络设计,深度神经网络代码matlab
    自己动手写乞丐版线程池
    Java中的String类
    VISUAL SVN 5.6.0以上破解使用天数
    微信直播的开通方法以及特点是什么
    在Java中如何优雅的停止一个线程?可别再用Thread.stop()了!
    前端面试题 10 个「有用」JavaScript 代码片段
    JDK8 Stream测试
  • 原文地址:https://blog.csdn.net/qq_32716885/article/details/127401546