首页 > 其他分享 >运用事件与定时器实现字幕滚动效果(Qt开发)

运用事件与定时器实现字幕滚动效果(Qt开发)

时间:2023-08-05 22:32:09浏览次数:41  
标签:定时器 窗口 Qt void 字幕 offset Ticker event

1、效果展示

我们经常能够在外面看到那种滚动字幕,那么就拿qt来做一个吧。

运用事件与定时器实现字幕滚动效果(Qt开发)_ide

2、实现思路

实现一个窗口部件,这个窗口部件显示了一串文本标语,它会每t毫秒向左移动一个像素。如果窗口部件比文本宽,那么文本将会被多次重复,直到能够填满整个窗口部件的宽度为止。

3、滚动窗口部件

创建一个滚动窗口类,将其命名为ticker。

运用事件与定时器实现字幕滚动效果(Qt开发)_ide_02

3.1、成员变量

我们需要提供几个成员变量。

  • myText用来表示要显示的文本内容。
  • offset表示当前偏移量。
  • myTimerId表示定时器的ID编号。
QString myText;
    int offset;
    int myTimerId;

3.2、事件重写

需要重新实现了Ticker中的4个事件处理器,分别为paintEvent()、timerEvent()、showEvent()和 hideEvent();关于每个事件的职责后面再说。

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、成员方法

运用事件与定时器实现字幕滚动效果(Qt开发)_构造函数_03

还需要提供几个成员方法。关于每个方法的职责后面再说。

void setText(const QString& newText);
    QString text() const { return myText; }
    QSize sizeHint() const;

3.4、方法实现

1.构造函数

构造函数把 offset变量初始化为0。用来绘制文本的x坐标值就取自于这个offset 值。

定时器的ID通常是非零的,所以可以使用0来表示定时器还没有启动。

Ticker::Ticker(QWidget *parent)
    : QWidget{parent}
{
    offset = 0;
    myTimerId = 0;
}

2.setText函数

setText()函数用来设置要显示的文本。它调用update()强制执行一个重绘操作,并且调用updateGeometry()通知对Ticker窗口部件负责的布局管理器,提示该窗口部件的大小发生了变化。

void Ticker::setText(const QString &newText)
{
    myText = newText;
    update();
    updateGeometry();
}

3.sizeHint函数

sizeHint()函数返回文本所需的空间大小,并以此作为窗口部件的理想尺寸。QWidget::fontMetrics()函数返回一个QFontMetrics对象;可以用这个对象查询并获得与这个窗口部件字体相关的信息。

QSize Ticker::sizeHint() const
{
    return fontMetrics().size(0, text());
}

4.paintEvent事件

paintEvent()函数使用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定时器事件

系统每隔一定时间,都会调用一次timerEvent()函数。

通过在offset上加1来模拟移动,从而形成文本宽度的连续滚动。然后,它使用QWidget::scroll()把窗口部件的内容向左滚动一个像素。

如果这个定时器事件不是我们所关注的那个定时器,就可以把它传递给基类。

这里也可以调用update()代替scrol(),但使用scroll()会更有效率,因为它只是简单地移动屏幕上已经存在的像素并且只对这个窗口部件的新显示区域(此时,只是一个1像素乘以宽度的像素条)产生一个绘制事件。

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()函数用来启动个定时器。QObject::startTimer()调用会返回一个ID数字,用这个数字识别该定时器。QObject支持多个独立的定时器,每一个都可以有自己的时间间隔。

在startTimer()调用之后,大约每30毫秒Qt都会产生一个定时器事件。至于具体的时间精度,则取决于所在的操作系统。

我们也可以在Ticker的构造函数中完成startTimer()的调用,但是只有在窗口部件实际可见的时候,才有必要保存由Qt产生的定时器事件的那些资源。让资源合理利用。

void Ticker::showEvent(QShowEvent *event)
{
    Q_UNUSED(event);
    myTimerId = startTimer(30);
}

7.hideEvent隐藏事件

hideEvent()函数调用QObject::killTimer()来停止该定时器。

void Ticker::hideEvent(QHideEvent *event)
{
    killTimer(myTimerId);
    myTimerId = 0;
}

定时器事件是一种低级事件,而且如果需要多个定时器时,保持对所有定时器ID的跟踪将会变得很麻烦。

在这种情况下,通常更为简单的方式是为每一个定时器分别创建一个QTimer对象。QTimer会在每个时间间隔发射timeout()信号。当然QTimer也提供了一个非常方便的接口,可用于单触发定时器(只触发一次的定时器)QTimer::singleShot(t, this, &Ticker::onTimer)。

标签:定时器,窗口,Qt,void,字幕,offset,Ticker,event
From: https://blog.51cto.com/u_15641375/6978739

相关文章

  • Qt 隐式共享
    Qt中的许多c++类使用隐式数据共享来最大化资源使用并最小化复制。隐式共享类作为参数传递时既安全又高效,因为只传递指向数据的指针,并且只有当函数写入数据时才会复制数据,即写时复制。 概述共享类由指向包含引用计数和数据的共享数据块的指针组成。 当创建共享对象时,它将引......
  • 最简单的Qt连接MYSQL的方法
    最简单的Qt连接MYSQL的方法⭐当我试图在项目中连接本地的mysql时,反复出现:QMYSQLdrivernotloaded,显示没有成功加载mysql的驱动,在网上查询了很多教程和视频,大多为互相转载且老旧,耗费了大半天还是没有构建成功,通常的解决方法是在本地构建mysql驱动(通过安装qt时勾选的src选项里......
  • Qt5Agg TxAgg和WXAgg的区别
    https://www.oschina.net/question/12_3252 AGG,全名:Anti-GrainGeometry,是一个开源的、高效的2D图形库。AGG的功能与GDI+的功能非常类似,但提供了比GDI+更灵活的编程接口,其产生的图形的质量也非常高,而且它是跨平台的,其宣传可以在非常多的操作系统上运行。主要的功能有:1、支......
  • QT(4)信号、SLOT和QMap - Addressbook例子2
    在之前的MeeGo开发者(五):QT(3)对象和继承小例子基础上,我们增加三个button,参考http://doc.qt.nokia.com/latest/tutorials-addressbook-part2.html、http://doc.qt.nokia.com/latest/tutorials-addressbook-part3.html和http://doc.qt.nokia.com/latest/tutorials-addressbook-part......
  • 初识QT、窗口以及信号槽
    1基本规范:无论是写什么样的代码,第一步都应该是创建一个程序对象#include<QApplication>intmain(intargc,char*argv[]){QApplicationa(argc,argv);//创建对象并调用构造函数returna.exec();//因为是gui界面开发,那么程序的生存周期应该是一直存在的}2d......
  • 十五、基于MQTT协议上传属性至ONENET Studio
    1.准备工作(1)下载MQTT透传固件(安心可官网下载即可)(2)下载MQTT固件到ESP82662.AT指令连接设备上传属性值(1)AT\r\n(2)AT+RST\r\n(3)AT+CWMODE=1\r\n(4)AT+CWDHCP=1,1\r\n(5)AT+CWJAP="WIFISSID","密码"\r\n//连接路由器(6)AT+MQTTUSERCFG=0,1,"设备名/设备id","产品I......
  • 【OpenHarmony内核编程接口】介绍定时器管理两种定时器以及案例演示
    前言本文介绍了内核编程接口之软定时器软定时器软定时器含义软件定时器(Timer),是基于系统时钟tick且由软件来模拟的定时器,当经过设定的tick计数值后会触发用户定义的回调函数ps1:定时器触发函数的执行,不是线程ps2:当定时器到期时,将执行回调函数以运行特定的代码ps3:定时精度......
  • Qt 在线程中invokeMethod采用QueuedConnection模式,调用带指针参数槽,实际不会调用
    widgetObject有操函数Test:voidTest(int*v);在线程中调用Test,会被忽略,实际不会调用。QMetaObject::invokeMethod(widgetObject,"Test",Qt::QueuedConnection,Q_ARG(int*,&v));下面是网上找的理由: 在同一个线程中当信号和槽都在同一个线程中时,值传递参数和引用传递参数有......
  • Qt 通过ADS实现倍福TwinCAT通信
    ADS通信分为两种:同步方式和异步方式。同步方式ADS客户端向ADS服务器发送ADS请求,在通信过程中客户端程序停止执行,直到获得ADS服务器返回的响应又可分为变量名方式和地址方式异步方式ADS客户端向ADS服务器发送ADS请求,同时客户端继续自己的工作。ADS服务器处理......
  • Qt 调用倍福TwinCAT通讯模块(TcAdsDll)
    Qt实现TwinCAT通讯目前这种方式是通过调用TwinCAT提供的AdsApi与倍福PLC通讯的。要求本机安装TwinCAT(无需作为主机,但是可能这个api依赖TwinCAT的一些服务)。关于AdsApi的官方资料请看这里,有函数的详细解释,还有例子。你值得拥有。https://infosys.beckhoff.com/english.php?conte......