Qt使用事件與定時(shí)器實(shí)現(xiàn)字幕滾動(dòng)效果
1、效果展示
我們經(jīng)常能夠在外面看到那種滾動(dòng)字幕,那么就拿qt來(lái)做一個(gè)吧。

2、實(shí)現(xiàn)思路
實(shí)現(xiàn)一個(gè)窗口部件,這個(gè)窗口部件顯示了一串文本標(biāo)語(yǔ),它會(huì)每t毫秒向左移動(dòng)一個(gè)像素。如果窗口部件比文本寬,那么文本將會(huì)被多次重復(fù),直到能夠填滿整個(gè)窗口部件的寬度為止。
3、滾動(dòng)窗口部件
創(chuàng)建一個(gè)滾動(dòng)窗口類(lèi),將其命名為ticker。
3.1、成員變量
我們需要提供幾個(gè)成員變量。
- myText用來(lái)表示要顯示的文本內(nèi)容。
- offset表示當(dāng)前偏移量。
- myTimerId表示定時(shí)器的ID編號(hào)。
QString myText;
int offset;
int myTimerId;3.2、事件重寫(xiě)
需要重新實(shí)現(xiàn)了Ticker中的4個(gè)事件處理器,分別為paintEvent()、timerEvent()、showEvent()和 hideEvent();關(guān)于每個(gè)事件的職責(zé)后面再說(shuō)。
virtual void paintEvent(QPaintEvent* event) override; // 繪制事件
virtual void timerEvent(QTimerEvent* event) override; // 定時(shí)器事件
virtual void showEvent(QShowEvent* event) override; // 顯示事件
virtual void hideEvent(QHideEvent* event) override; // 隱藏事件3.3、成員方法
還需要提供幾個(gè)成員方法。關(guān)于每個(gè)方法的職責(zé)后面再說(shuō)。
void setText(const QString& newText);
QString text() const { return myText; }
QSize sizeHint() const;3.4、方法實(shí)現(xiàn)
1.構(gòu)造函數(shù)
構(gòu)造函數(shù)把 offset變量初始化為0。用來(lái)繪制文本的x坐標(biāo)值就取自于這個(gè)offset 值。
定時(shí)器的ID通常是非零的,所以可以使用0來(lái)表示定時(shí)器還沒(méi)有啟動(dòng)。
Ticker::Ticker(QWidget *parent)
: QWidget{parent}
{
offset = 0;
myTimerId = 0;
}2.setText函數(shù)
setText()函數(shù)用來(lái)設(shè)置要顯示的文本。它調(diào)用update()強(qiáng)制執(zhí)行一個(gè)重繪操作,并且調(diào)用updateGeometry()通知對(duì)Ticker窗口部件負(fù)責(zé)的布局管理器,提示該窗口部件的大小發(fā)生了變化。
void Ticker::setText(const QString &newText)
{
myText = newText;
update();
updateGeometry();
}3.sizeHint函數(shù)
sizeHint()函數(shù)返回文本所需的空間大小,并以此作為窗口部件的理想尺寸。QWidget::fontMetrics()函數(shù)返回一個(gè)QFontMetrics對(duì)象;可以用這個(gè)對(duì)象查詢并獲得與這個(gè)窗口部件字體相關(guān)的信息。
QSize Ticker::sizeHint() const
{
return fontMetrics().size(0, text());
}4.paintEvent事件
paintEvent()函數(shù)使用QPainter::drawText()繪制文本。它使用fontMetrics()確定文本在水平方向上所需要的空間,并且在考慮offset值的同時(shí),多次繪制文本,直到能夠填充整個(gè)窗口部件的寬度為止。
void Ticker::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
int textWidth = fontMetrics().width(text());
if(textWidth < 1)
{
return;
}
int x = -offset;
while(x < width())
{
painter.drawText(x, 0, textWidth, height(), Qt::AlignLeft | Qt::AlignVCenter, text());
x += textWidth;
}
}5.timerEvent定時(shí)器事件
系統(tǒng)每隔一定時(shí)間,都會(huì)調(diào)用一次timerEvent()函數(shù)。
通過(guò)在offset上加1來(lái)模擬移動(dòng),從而形成文本寬度的連續(xù)滾動(dòng)。然后,它使用QWidget::scroll()把窗口部件的內(nèi)容向左滾動(dòng)一個(gè)像素。
如果這個(gè)定時(shí)器事件不是我們所關(guān)注的那個(gè)定時(shí)器,就可以把它傳遞給基類(lèi)。
這里也可以調(diào)用update()代替scrol(),但使用scroll()會(huì)更有效率,因?yàn)樗皇呛?jiǎn)單地移動(dòng)屏幕上已經(jīng)存在的像素并且只對(duì)這個(gè)窗口部件的新顯示區(qū)域(此時(shí),只是一個(gè)1像素乘以寬度的像素條)產(chǎn)生一個(gè)繪制事件。
void Ticker::timerEvent(QTimerEvent *event)
{
if(event->timerId() == myTimerId)
{
++offset;
if(offset >= fontMetrics().width(text()))
{
offset = 0;
}
scroll(-1, 0);
}
else
{
QWidget::timerEvent(event);
}
}6.showEvent顯示事件
showEvent()函數(shù)用來(lái)啟動(dòng)個(gè)定時(shí)器。QObject::startTimer()調(diào)用會(huì)返回一個(gè)ID數(shù)字,用這個(gè)數(shù)字識(shí)別該定時(shí)器。QObject支持多個(gè)獨(dú)立的定時(shí)器,每一個(gè)都可以有自己的時(shí)間間隔。
在startTimer()調(diào)用之后,大約每30毫秒Qt都會(huì)產(chǎn)生一個(gè)定時(shí)器事件。至于具體的時(shí)間精度,則取決于所在的操作系統(tǒng)。
我們也可以在Ticker的構(gòu)造函數(shù)中完成startTimer()的調(diào)用,但是只有在窗口部件實(shí)際可見(jiàn)的時(shí)候,才有必要保存由Qt產(chǎn)生的定時(shí)器事件的那些資源。讓資源合理利用。
void Ticker::showEvent(QShowEvent *event)
{
Q_UNUSED(event);
myTimerId = startTimer(30);
}7.hideEvent隱藏事件
hideEvent()函數(shù)調(diào)用QObject::killTimer()來(lái)停止該定時(shí)器。
void Ticker::hideEvent(QHideEvent *event)
{
killTimer(myTimerId);
myTimerId = 0;
}定時(shí)器事件是一種低級(jí)事件,而且如果需要多個(gè)定時(shí)器時(shí),保持對(duì)所有定時(shí)器ID的跟蹤將會(huì)變得很麻煩。
在這種情況下,通常更為簡(jiǎn)單的方式是為每一個(gè)定時(shí)器分別創(chuàng)建一個(gè)QTimer對(duì)象。QTimer會(huì)在每個(gè)時(shí)間間隔發(fā)射timeout()信號(hào)。當(dāng)然QTimer也提供了一個(gè)非常方便的接口,可用于單觸發(fā)定時(shí)器(只觸發(fā)一次的定時(shí)器)QTimer::singleShot(t, this, &Ticker::onTimer);
到此這篇關(guān)于Qt使用事件與定時(shí)器實(shí)現(xiàn)字幕滾動(dòng)效果的文章就介紹到這了,更多相關(guān)Qt字幕滾動(dòng)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Qt兩種定時(shí)器使用實(shí)現(xiàn)方式
- Qt定時(shí)器(QTimer)的3種使用方法
- Qt定時(shí)器類(lèi)QTimer使用詳解與注意事項(xiàng)
- QT定時(shí)器事件的實(shí)現(xiàn)示例
- Qt實(shí)現(xiàn)定時(shí)器的兩種方法分享
- Qt實(shí)現(xiàn)高精度定時(shí)器
- Qt實(shí)現(xiàn)線程與定時(shí)器的方法
- Qt基于定時(shí)器實(shí)現(xiàn)動(dòng)圖展示效果
- Qt基礎(chǔ)開(kāi)發(fā)之Qt多線程類(lèi)QThread與Qt定時(shí)器類(lèi)QTimer的詳細(xì)方法與實(shí)例
- Qt定時(shí)器和隨機(jī)數(shù)詳解
- Qt中定時(shí)器 QTimerEvent 和 QTimer的使用
相關(guān)文章
C++實(shí)現(xiàn)結(jié)束應(yīng)用進(jìn)程小工具
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)結(jié)束應(yīng)用進(jìn)程小工具,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-05-05
淺談Linux環(huán)境下并發(fā)編程中C語(yǔ)言fork()函數(shù)的使用
fork函數(shù)在Linux中可以創(chuàng)建子進(jìn)程即一個(gè)新的進(jìn)程,這里我們根據(jù)實(shí)例來(lái)淺談Linux環(huán)境下并發(fā)編程中C語(yǔ)言fork()函數(shù)的使用,需要的朋友可以參考下2016-06-06
基于C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易的掃雷游戲
這篇文章主要為大家詳細(xì)介紹了基于C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易的掃雷游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06
QT已有項(xiàng)目導(dǎo)入工程時(shí)注意事項(xiàng)圖文詳解
QT開(kāi)發(fā)這幾年大大小小項(xiàng)目做了不少,花了點(diǎn)時(shí)間對(duì)知識(shí)點(diǎn)總結(jié)整合了一部分,下面這篇文章主要給大家介紹了關(guān)于QT已有項(xiàng)目導(dǎo)入工程時(shí)注意事項(xiàng)的相關(guān)資料,需要的朋友可以參考下2023-11-11
C語(yǔ)言實(shí)現(xiàn)紙牌計(jì)算24點(diǎn)小游戲
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)紙牌計(jì)算24點(diǎn)小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-10-10
java 出現(xiàn)NullPointerException的原因及解決辦法
這篇文章主要介紹了java 出現(xiàn)NullPointerException的原因及解決辦法的相關(guān)資料,這里說(shuō)明出現(xiàn)NullPointerException 的原因的總結(jié),并說(shuō)明該如何解決,需要的朋友可以參考下2017-08-08
探討:C++中函數(shù)返回引用的注意事項(xiàng)
本篇文章是對(duì)C++中函數(shù)返回引用的注意事項(xiàng)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
C語(yǔ)言初階之?dāng)?shù)組詳細(xì)介紹
大家好,本篇文章主要講的是C語(yǔ)言初階之?dāng)?shù)組詳細(xì)介紹,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽2021-12-12
C++實(shí)現(xiàn)基于不相交集合的O(mlgn)復(fù)雜度的kruskal算法
這篇文章主要為大家詳細(xì)介紹了C++如何實(shí)現(xiàn)基于不相交集合的O(mlgn)復(fù)雜度的kruskal算法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2023-02-02

