Qt模仿實(shí)現(xiàn)文字浮動(dòng)字母的效果
前沿
最近可能是小視頻著魔了,尤其是動(dòng)畫(huà)字幕效果的,身為一名技術(shù)開(kāi)發(fā)人員,當(dāng)然是想試一試了,哪怕只是簡(jiǎn)單的移動(dòng)也是可以的~
這不,說(shuō)干就干拿起來(lái)我的C++語(yǔ)言就要嘗試,還好使用的Qt框架,這樣是使用MFC框架寫(xiě)小demo,真的好困難呀!
先來(lái)看一看我實(shí)現(xiàn)的效果吧~
效果很簡(jiǎn)單就是文本向上移動(dòng),在移動(dòng)過(guò)程中文字整體變大或縮小。
那么,我就來(lái)講解下我是如何實(shí)現(xiàn)的吧!
功能實(shí)現(xiàn)
在實(shí)現(xiàn)這個(gè)文本移動(dòng)的效果過(guò)程中,用到了以下幾個(gè)功能:
1:定時(shí)器
2:QLabel控件自繪
定時(shí)器操作
在QWidget中提供了一個(gè)定時(shí)器操作函數(shù),我們只需要繼承就可以實(shí)現(xiàn)了
virtual void timerEvent(QTimerEvent *event);
使用QWidget自帶的定時(shí)器操作時(shí),就不需要new QTiemr的方式了,只需要使用int值記錄當(dāng)前開(kāi)啟定時(shí)器編號(hào),等達(dá)到觸發(fā)時(shí)間后進(jìn)行處理即可。
文本偏移實(shí)現(xiàn)
首先在實(shí)現(xiàn)之前,先來(lái)講解下主要流程是怎么回事吧!
1:定義文本移動(dòng)定時(shí)器
2:每一秒觸發(fā)一次,每次觸發(fā)都需要?jiǎng)?chuàng)建一個(gè)新的控件用于展示內(nèi)容。
3:觸發(fā)后將已經(jīng)展示的文本遍歷方式向上整體偏移,偏移過(guò)程中會(huì)根據(jù)隨機(jī)數(shù),隨機(jī)更改文本字體的大小。
4:字體變化,導(dǎo)致文本的寬度高度變更,用新的寬度、高度計(jì)算偏移后的位置。
在這里,我們可以對(duì)QLabel控件進(jìn)行重繪,假設(shè)叫做QCustomLabel,父類是QLabel。那么我來(lái)一步一步地講解我是如何實(shí)現(xiàn)定時(shí)器偏移的吧~
第一步
定義容器用于存儲(chǔ)需要展示的文本內(nèi)容,這里可以用一個(gè)簡(jiǎn)單的容器vector來(lái)記錄,std::vector< std::string >m_vetContent;
第二步
定義容器用于存儲(chǔ)已經(jīng)展示過(guò)的文本控件,使用QVector來(lái)記錄,QVector<QCustomLabel*> m_vetControls;
為什么第一步和第二步都是用vector記錄,但是一個(gè)使用C++的,另一個(gè)使用Qt的呢?
其實(shí)在第一步與第二步存儲(chǔ)過(guò)程中,都可以使用QVector來(lái)進(jìn)行記錄,有一點(diǎn)需要注意的是,第二步存儲(chǔ)必須使用QVector。
為什么?因?yàn)関ector與QVector存儲(chǔ)都是先入先出的形式,我們?cè)谟涗浛丶羔槙r(shí),最先拿出的控件指針應(yīng)該是后插入的數(shù)據(jù)。在QVector中從前端插入數(shù)據(jù)更為方便些,索性這兩個(gè)步驟用的容器就稍微有一些差別了,你get到了嗎?
第三步
觸發(fā)定時(shí)器后,臨時(shí)創(chuàng)建顯示文本的控件數(shù)據(jù),并及時(shí)存儲(chǔ)到容器m_vetControls中,以防銷(xiāo)毀窗口時(shí)不及時(shí)銷(xiāo)毀指針導(dǎo)致的內(nèi)存泄漏問(wèn)題。
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()方法,每次存儲(chǔ)的數(shù)據(jù)都最先展示,也就是將數(shù)據(jù)存儲(chǔ)到下標(biāo)為0的位置下。
第四步
數(shù)據(jù)存儲(chǔ)后,更新所有展示的文本控件位置,這里使用:UpdateShowRectStyle()函數(shù)進(jìn)行實(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)遍歷整個(gè)存儲(chǔ)控件指針的數(shù)據(jù)內(nèi)容,在更新位置的同時(shí)更改文本縮放大?。ㄒ簿褪亲兓煮w大小),獲取最新的變更位置,重新獲取寬度、高度。
假設(shè)當(dāng)前的高度是0時(shí),說(shuō)明是第一條數(shù)據(jù)需要變更,偏移的位置,直接是控件的高度; 假設(shè)當(dāng)前的高度非0時(shí),說(shuō)明是偏移過(guò)程中的某一條數(shù)據(jù),因?yàn)槭窍蛏掀?,所有每次?jì)算偏移后的高度時(shí),都需要做減法,如果是向下偏移,每次計(jì)算偏移后的高度就是做加法了。
第五步
當(dāng)讀寫(xiě)完所有的顯示內(nèi)容時(shí),停止定時(shí)器操作
if (m_nTimerTriggerNumber == m_vetContent.size()) { killTimer(m_nTimerId); m_nTimerId = 0; }
到這里,文字自動(dòng)偏移的功能就實(shí)現(xiàn)了,接下來(lái)我們來(lái)講一講是如何自繪QLabel控件吧~
控件自繪
首先我們需要定義QLabel的自繪類,這里我給除了簡(jiǎn)單的框架,以后需要什么功能直接追加就可以啦~
.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() { }
想要實(shí)現(xiàn)什么功能,就只需要在這個(gè)基礎(chǔ)上擴(kuò)充就可以了。
在自繪QLabel中有兩個(gè)重點(diǎn)
1:如何根據(jù)字體的大小固定文本區(qū)域?
2:文字閃爍效果實(shí)現(xiàn)
根據(jù)這兩個(gè)重點(diǎn)來(lái)繪制QLable控件吧!
功能1:
字體的大小可以使用隨機(jī)數(shù)qrand()來(lái)實(shí)現(xiàn)。
使用方法:
QTime time = QTime::currentTime(); qsrand(time.msec() + time.second() * 1000); int nFontSize = qrand() % 30 + 20;
這種方式生成的隨機(jī)數(shù)保證了唯一性。
根據(jù)字體大小,設(shè)置QFont的屬性
QFont fontContent =this->font(); //設(shè)置:字體樣式:微軟雅黑 fontContent.setFamily("Microsoft YaHei"); //設(shè)置:字體大?。?2 fontContent.setPixelSize(nFontSize); //字體綁定 this->setFont(fontContent);
重點(diǎn)來(lái)啦?。?!
設(shè)置了字體風(fēng)格之后,這時(shí)候我們是可以獲取到字體的高度的,但是整體的寬度是獲取不到的需要?jiǎng)討B(tài)獲取。
QFontMetrics metrics(font()); int nheight = metrics.height(); //設(shè)置內(nèi)容并存儲(chǔ)文本內(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); //開(kāi)啟定時(shí)器 m_nTimerId = startTimer(100); return size;
功能2:
文字顏色漸變展示。
這個(gè)功能很簡(jiǎn)單,核心就是實(shí)時(shí)的更新QColor值,這里我使用了隨機(jī)數(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); //單個(gè)字符繪制 painter->drawText(x, y, QString(m_qsTextContent[i])); //計(jì)算下一個(gè)字符的x坐標(biāo)起始點(diǎn) x += metrics.width(m_qsTextContent[i]); }
總結(jié)
到這里,文字移動(dòng)效果就已經(jīng)實(shí)現(xiàn)了,功能比較簡(jiǎn)單,唯一的難點(diǎn)就在于文字風(fēng)格變動(dòng)時(shí),區(qū)域的變化,只要我們了解了變化規(guī)律,位置展示還不是小菜一碟嗎?
以上就是Qt模仿實(shí)現(xiàn)文字浮動(dòng)字母的效果的詳細(xì)內(nèi)容,更多關(guān)于Qt文字浮動(dòng)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C++ 中約瑟夫環(huán)替換計(jì)數(shù)器m(數(shù)組解決)
這篇文章主要介紹了C++ 中約瑟夫環(huán)替換計(jì)數(shù)器m(數(shù)組解決)的相關(guān)資料,需要的朋友可以參考下2017-05-05C++數(shù)據(jù)結(jié)構(gòu)與算法之雙緩存隊(duì)列實(shí)現(xiàn)方法詳解
這篇文章主要介紹了C++數(shù)據(jù)結(jié)構(gòu)與算法之雙緩存隊(duì)列實(shí)現(xiàn)方法,結(jié)合實(shí)例形式分析了雙緩存隊(duì)列的原理、實(shí)現(xiàn)方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下2017-08-08Qt實(shí)現(xiàn)可以計(jì)算大數(shù)的簡(jiǎn)單計(jì)算器
計(jì)算器是我們生活中很常見(jiàn)的東西,它可以由多種語(yǔ)言多種方式來(lái)實(shí)現(xiàn)。本文主要介紹的是基于C++語(yǔ)言,由QT實(shí)現(xiàn)的可以計(jì)算大數(shù)的簡(jiǎn)單計(jì)算器,需要的可以參考一下2022-12-12C語(yǔ)言實(shí)現(xiàn)變色進(jìn)度條
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)一個(gè)變色的進(jìn)度條,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01詳解C語(yǔ)言中sizeof如何在自定義函數(shù)中正常工作
在main函數(shù)中,sizeof是可以正常工作的,但是在自定義函數(shù)中就不可以了。所以本文將為大家詳細(xì)講解一下如何解決這一問(wèn)題,感興趣的可以了解一下2022-05-05在C++程序中開(kāi)啟和禁用Windows設(shè)備的無(wú)線網(wǎng)卡的方法
這篇文章主要介紹了在C++程序中開(kāi)啟和禁用Windows設(shè)備的無(wú)線網(wǎng)卡的方法,包括一些常見(jiàn)錯(cuò)誤的分析與解決,需要的朋友可以參考下2016-03-03C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單學(xué)生學(xué)籍管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單學(xué)生學(xué)籍管理系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01