Qt模仿實現(xiàn)文字浮動字母的效果
前沿
最近可能是小視頻著魔了,尤其是動畫字幕效果的,身為一名技術(shù)開發(fā)人員,當然是想試一試了,哪怕只是簡單的移動也是可以的~
這不,說干就干拿起來我的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值記錄當前開啟定時器編號,等達到觸發(fā)時間后進行處理即可。
文本偏移實現(xiàn)
首先在實現(xiàn)之前,先來講解下主要流程是怎么回事吧!
1:定義文本移動定時器
2:每一秒觸發(fā)一次,每次觸發(fā)都需要創(chuàng)建一個新的控件用于展示內(nèi)容。
3:觸發(fā)后將已經(jīng)展示的文本遍歷方式向上整體偏移,偏移過程中會根據(jù)隨機數(shù),隨機更改文本字體的大小。
4:字體變化,導致文本的寬度高度變更,用新的寬度、高度計算偏移后的位置。
在這里,我們可以對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中,以防銷毀窗口時不及時銷毀指針導致的內(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ù)存儲到下標為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)容,在更新位置的同時更改文本縮放大小(也就是變化字體大?。@取最新的變更位置,重新獲取寬度、高度。
假設(shè)當前的高度是0時,說明是第一條數(shù)據(jù)需要變更,偏移的位置,直接是控件的高度; 假設(shè)當前的高度非0時,說明是偏移過程中的某一條數(shù)據(jù),因為是向上偏移,所有每次計算偏移后的高度時,都需要做減法,如果是向下偏移,每次計算偏移后的高度就是做加法了。
第五步
當讀寫完所有的顯示內(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è)置了字體風格之后,這時候我們是可以獲取到字體的高度的,但是整體的寬度是獲取不到的需要動態(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坐標起始點 x += metrics.width(m_qsTextContent[i]); }
總結(jié)
到這里,文字移動效果就已經(jīng)實現(xiàn)了,功能比較簡單,唯一的難點就在于文字風格變動時,區(qū)域的變化,只要我們了解了變化規(guī)律,位置展示還不是小菜一碟嗎?
以上就是Qt模仿實現(xiàn)文字浮動字母的效果的詳細內(nèi)容,更多關(guān)于Qt文字浮動的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C++ 中約瑟夫環(huán)替換計數(shù)器m(數(shù)組解決)
這篇文章主要介紹了C++ 中約瑟夫環(huán)替換計數(shù)器m(數(shù)組解決)的相關(guān)資料,需要的朋友可以參考下2017-05-05C++數(shù)據(jù)結(jié)構(gòu)與算法之雙緩存隊列實現(xiàn)方法詳解
這篇文章主要介紹了C++數(shù)據(jù)結(jié)構(gòu)與算法之雙緩存隊列實現(xiàn)方法,結(jié)合實例形式分析了雙緩存隊列的原理、實現(xiàn)方法與相關(guān)注意事項,需要的朋友可以參考下2017-08-08詳解C語言中sizeof如何在自定義函數(shù)中正常工作
在main函數(shù)中,sizeof是可以正常工作的,但是在自定義函數(shù)中就不可以了。所以本文將為大家詳細講解一下如何解決這一問題,感興趣的可以了解一下2022-05-05在C++程序中開啟和禁用Windows設(shè)備的無線網(wǎng)卡的方法
這篇文章主要介紹了在C++程序中開啟和禁用Windows設(shè)備的無線網(wǎng)卡的方法,包括一些常見錯誤的分析與解決,需要的朋友可以參考下2016-03-03