使用Qt開發(fā)實現(xiàn)字幕滾動效果
1、效果展示
我們經(jīng)常能夠在外面看到那種滾動字幕,那么就拿qt來做一個吧。
2、實現(xiàn)思路
實現(xiàn)一個窗口部件,這個窗口部件顯示了一串文本標語,它會每t毫秒向左移動一個像素。如果窗口部件比文本寬,那么文本將會被多次重復,直到能夠填滿整個窗口部件的寬度為止。
3、滾動窗口部件
創(chuàng)建一個滾動窗口類,將其命名為ticker。
3.1、成員變量
我們需要提供幾個成員變量。
- myText用來表示要顯示的文本內(nèi)容。
- offset表示當前偏移量。
- myTimerId表示定時器的ID編號。
QString myText; int offset; int myTimerId;
3.2、事件重寫
需要重新實現(xiàn)了Ticker中的4個事件處理器,分別為paintEvent()、timerEvent()、showEvent()和 hideEvent();關(guān)于每個事件的職責后面再說。
virtual void paintEvent(QPaintEvent* event) override; // 繪制事件 virtual void timerEvent(QTimerEvent* event) override; // 定時器事件 virtual void showEvent(QShowEvent* event) override; // 顯示事件 virtual void hideEvent(QHideEvent* event) override; // 隱藏事件
3.3、成員方法
還需要提供幾個成員方法。關(guān)于每個方法的職責后面再說。
void setText(const QString& newText); QString text() const { return myText; } QSize sizeHint() const;
3.4、方法實現(xiàn)
1.構(gòu)造函數(shù)
構(gòu)造函數(shù)把 offset變量初始化為0。用來繪制文本的x坐標值就取自于這個offset 值。
定時器的ID通常是非零的,所以可以使用0來表示定時器還沒有啟動。
Ticker::Ticker(QWidget *parent) : QWidget{parent} { offset = 0; myTimerId = 0; }
2.setText函數(shù)
setText()函數(shù)用來設(shè)置要顯示的文本。它調(diào)用update()強制執(zhí)行一個重繪操作,并且調(diào)用updateGeometry()通知對Ticker窗口部件負責的布局管理器,提示該窗口部件的大小發(fā)生了變化。
void Ticker::setText(const QString &newText) { myText = newText; update(); updateGeometry(); }
3.sizeHint函數(shù)
sizeHint()函數(shù)返回文本所需的空間大小,并以此作為窗口部件的理想尺寸。QWidget::fontMetrics()函數(shù)返回一個QFontMetrics對象;可以用這個對象查詢并獲得與這個窗口部件字體相關(guān)的信息。
QSize Ticker::sizeHint() const { return fontMetrics().size(0, text()); }
4.paintEvent事件
paintEvent()函數(shù)使用QPainter::drawText()繪制文本。它使用fontMetrics()確定文本在水平方向上所需要的空間,并且在考慮offset值的同時,多次繪制文本,直到能夠填充整個窗口部件的寬度為止。
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定時器事件
系統(tǒng)每隔一定時間,都會調(diào)用一次timerEvent()函數(shù)。
通過在offset上加1來模擬移動,從而形成文本寬度的連續(xù)滾動。然后,它使用QWidget::scroll()把窗口部件的內(nèi)容向左滾動一個像素。
如果這個定時器事件不是我們所關(guān)注的那個定時器,就可以把它傳遞給基類。
這里也可以調(diào)用update()代替scrol(),但使用scroll()會更有效率,因為它只是簡單地移動屏幕上已經(jīng)存在的像素并且只對這個窗口部件的新顯示區(qū)域(此時,只是一個1像素乘以寬度的像素條)產(chǎn)生一個繪制事件。
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ù)用來啟動個定時器。QObject::startTimer()調(diào)用會返回一個ID數(shù)字,用這個數(shù)字識別該定時器。QObject支持多個獨立的定時器,每一個都可以有自己的時間間隔。
在startTimer()調(diào)用之后,大約每30毫秒Qt都會產(chǎn)生一個定時器事件。至于具體的時間精度,則取決于所在的操作系統(tǒng)。
我們也可以在Ticker的構(gòu)造函數(shù)中完成startTimer()的調(diào)用,但是只有在窗口部件實際可見的時候,才有必要保存由Qt產(chǎn)生的定時器事件的那些資源。讓資源合理利用。
void Ticker::showEvent(QShowEvent *event) { Q_UNUSED(event); myTimerId = startTimer(30); }
7.hideEvent隱藏事件
hideEvent()函數(shù)調(diào)用QObject::killTimer()來停止該定時器。
void Ticker::hideEvent(QHideEvent *event) { killTimer(myTimerId); myTimerId = 0; }
定時器事件是一種低級事件,而且如果需要多個定時器時,保持對所有定時器ID的跟蹤將會變得很麻煩。
在這種情況下,通常更為簡單的方式是為每一個定時器分別創(chuàng)建一個QTimer對象。QTimer會在每個時間間隔發(fā)射timeout()信號。當然QTimer也提供了一個非常方便的接口,可用于單觸發(fā)定時器(只觸發(fā)一次的定時器)QTimer::singleShot(t, this, &Ticker::onTimer)。
以上就是使用Qt開發(fā)實現(xiàn)字幕滾動效果的詳細內(nèi)容,更多關(guān)于Qt字幕滾動的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C語言數(shù)組越界引發(fā)的死循環(huán)問題解決
本文主要介紹了C語言數(shù)組越界引發(fā)的死循環(huán)問題解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-08-08