Qt模仿實現(xiàn)文字浮動字母的效果
前沿
最近可能是小視頻著魔了,尤其是動畫字幕效果的,身為一名技術(shù)開發(fā)人員,當(dāng)然是想試一試了,哪怕只是簡單的移動也是可以的~
這不,說干就干拿起來我的C++語言就要嘗試,還好使用的Qt框架,這樣是使用MFC框架寫小demo,真的好困難呀!
先來看一看我實現(xiàn)的效果吧~

效果很簡單就是文本向上移動,在移動過程中文字整體變大或縮小。
那么,我就來講解下我是如何實現(xiàn)的吧!
功能實現(xiàn)
在實現(xiàn)這個文本移動的效果過程中,用到了以下幾個功能:
1:定時器
2:QLabel控件自繪
定時器操作
在QWidget中提供了一個定時器操作函數(shù),我們只需要繼承就可以實現(xiàn)了
virtual void timerEvent(QTimerEvent *event);
使用QWidget自帶的定時器操作時,就不需要new QTiemr的方式了,只需要使用int值記錄當(dāng)前開啟定時器編號,等達(dá)到觸發(fā)時間后進行處理即可。
文本偏移實現(xiàn)
首先在實現(xiàn)之前,先來講解下主要流程是怎么回事吧!
1:定義文本移動定時器
2:每一秒觸發(fā)一次,每次觸發(fā)都需要創(chuàng)建一個新的控件用于展示內(nèi)容。
3:觸發(fā)后將已經(jīng)展示的文本遍歷方式向上整體偏移,偏移過程中會根據(jù)隨機數(shù),隨機更改文本字體的大小。
4:字體變化,導(dǎo)致文本的寬度高度變更,用新的寬度、高度計算偏移后的位置。
在這里,我們可以對QLabel控件進行重繪,假設(shè)叫做QCustomLabel,父類是QLabel。那么我來一步一步地講解我是如何實現(xiàn)定時器偏移的吧~
第一步
定義容器用于存儲需要展示的文本內(nèi)容,這里可以用一個簡單的容器vector來記錄,std::vector< std::string >m_vetContent;
第二步
定義容器用于存儲已經(jīng)展示過的文本控件,使用QVector來記錄,QVector<QCustomLabel*> m_vetControls;
為什么第一步和第二步都是用vector記錄,但是一個使用C++的,另一個使用Qt的呢?
其實在第一步與第二步存儲過程中,都可以使用QVector來進行記錄,有一點需要注意的是,第二步存儲必須使用QVector。
為什么?因為vector與QVector存儲都是先入先出的形式,我們在記錄控件指針時,最先拿出的控件指針應(yīng)該是后插入的數(shù)據(jù)。在QVector中從前端插入數(shù)據(jù)更為方便些,索性這兩個步驟用的容器就稍微有一些差別了,你get到了嗎?
第三步
觸發(fā)定時器后,臨時創(chuàng)建顯示文本的控件數(shù)據(jù),并及時存儲到容器m_vetControls中,以防銷毀窗口時不及時銷毀指針導(dǎo)致的內(nèi)存泄漏問題。
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()方法,每次存儲的數(shù)據(jù)都最先展示,也就是將數(shù)據(jù)存儲到下標(biāo)為0的位置下。
第四步
數(shù)據(jù)存儲后,更新所有展示的文本控件位置,這里使用:UpdateShowRectStyle()函數(shù)進行實現(xiàn)哦~
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();循環(huán)遍歷整個存儲控件指針的數(shù)據(jù)內(nèi)容,在更新位置的同時更改文本縮放大?。ㄒ簿褪亲兓煮w大小),獲取最新的變更位置,重新獲取寬度、高度。
假設(shè)當(dāng)前的高度是0時,說明是第一條數(shù)據(jù)需要變更,偏移的位置,直接是控件的高度; 假設(shè)當(dāng)前的高度非0時,說明是偏移過程中的某一條數(shù)據(jù),因為是向上偏移,所有每次計算偏移后的高度時,都需要做減法,如果是向下偏移,每次計算偏移后的高度就是做加法了。
第五步
當(dāng)讀寫完所有的顯示內(nèi)容時,停止定時器操作
if (m_nTimerTriggerNumber == m_vetContent.size())
{
killTimer(m_nTimerId);
m_nTimerId = 0;
}到這里,文字自動偏移的功能就實現(xiàn)了,接下來我們來講一講是如何自繪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()
{
}想要實現(xiàn)什么功能,就只需要在這個基礎(chǔ)上擴充就可以了。
在自繪QLabel中有兩個重點
1:如何根據(jù)字體的大小固定文本區(qū)域?
2:文字閃爍效果實現(xiàn)
根據(jù)這兩個重點來繪制QLable控件吧!
功能1:
字體的大小可以使用隨機數(shù)qrand()來實現(xiàn)。
使用方法:
QTime time = QTime::currentTime(); qsrand(time.msec() + time.second() * 1000); int nFontSize = qrand() % 30 + 20;
這種方式生成的隨機數(shù)保證了唯一性。
根據(jù)字體大小,設(shè)置QFont的屬性
QFont fontContent =this->font();
//設(shè)置:字體樣式:微軟雅黑
fontContent.setFamily("Microsoft YaHei");
//設(shè)置:字體大?。?2
fontContent.setPixelSize(nFontSize);
//字體綁定
this->setFont(fontContent);重點來啦!??!
設(shè)置了字體風(fēng)格之后,這時候我們是可以獲取到字體的高度的,但是整體的寬度是獲取不到的需要動態(tài)獲取。
QFontMetrics metrics(font()); int nheight = metrics.height(); //設(shè)置內(nèi)容并存儲文本內(nèi)容 m_qsTextContent = QString::fromLocal8Bit(sText.c_str()); setFixedHeight(nheight); this->setText(m_qsTextContent); this->adjustSize(); int nwidth = this->width(); //設(shè)置自定義QLable控件的寬度以及高度 QSize size(nwidth , nheight); //開啟定時器 m_nTimerId = startTimer(100); return size;
功能2:
文字顏色漸變展示。
這個功能很簡單,核心就是實時的更新QColor值,這里我使用了隨機數(shù)使每次生成的顏色值都不相同
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++)
{
//設(shè)置:色調(diào)(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坐標(biāo)起始點
x += metrics.width(m_qsTextContent[i]);
}總結(jié)
到這里,文字移動效果就已經(jīng)實現(xiàn)了,功能比較簡單,唯一的難點就在于文字風(fēng)格變動時,區(qū)域的變化,只要我們了解了變化規(guī)律,位置展示還不是小菜一碟嗎?
以上就是Qt模仿實現(xiàn)文字浮動字母的效果的詳細(xì)內(nèi)容,更多關(guān)于Qt文字浮動的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C++超詳細(xì)講解隱藏私有屬性和方法的兩種實現(xiàn)方式
為了避免因為將類庫中的私有成員開放給類的使用方而導(dǎo)致的軟件邏輯外泄,因此需要將對外代碼中的私有成員隱藏起來,下面我們來了解一下隱藏私有屬性和方法的兩種實現(xiàn)方式2022-05-05
C++ LeetCode1775通過最少操作次數(shù)使數(shù)組和相等
這篇文章主要為大家介紹了C++ LeetCode1775通過最少操作次數(shù)使數(shù)組和相等,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-12-12
C語言中二維數(shù)組作為函數(shù)參數(shù)來傳遞的三種方法
這篇文章主要給大家介紹了關(guān)于C語言中二維數(shù)組作為函數(shù)參數(shù)來傳遞的三種方法,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用C語言有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
C語言雙向鏈表實現(xiàn)根據(jù)使用頻率安排元素位置的功能實例代碼
這篇文章主要介紹了C語言雙向鏈表實現(xiàn)根據(jù)使用頻率安排元素位置的功能實例代碼的相關(guān)資料,需要的朋友可以參考下2017-03-03
C++輕松實現(xiàn)字符串與字符數(shù)組的相互轉(zhuǎn)換
本文詳細(xì)介紹了如何在C++中通過c_str()和strcpy()函數(shù)將字符串轉(zhuǎn)換為字符數(shù)組,以及使用for循環(huán)、+運算符、重載=和內(nèi)置構(gòu)造函數(shù)將字符數(shù)組轉(zhuǎn)換為字符串的方法,需要的朋友可以參考下2025-03-03
C語言結(jié)構(gòu)體嵌套與對齊超詳細(xì)講解
這篇文章主要介紹了C語言結(jié)構(gòu)體嵌套與對齊,C語言中結(jié)構(gòu)體是一種構(gòu)造類型,和數(shù)組、基本數(shù)據(jù)類型一樣,可以定義指向該種類型的指針。結(jié)構(gòu)體指針的定義類似其他基本數(shù)據(jù)類型的定義2022-12-12

