Qt并不是一定要用来做界面开发,其实Qt内部的很多非界面模块也十分优秀,本文紧接着Qt系列的上一篇文章,继续介绍如何使用QObject做基类来开发模块。本文以一个计时器为例来介绍Qt的Event System的入门知识,后续文章会继续深入介绍Event相关内容。
事件体系(Event System)
Qt帮助文本对“Event System”的解释是:“In Qt, events are objects, derived from the abstract QEvent class, that represent things that have happened either within an application or as a result of outside activity that the application needs to know about. Events can be received and handled by any instance of a QObject subclass, but they are especially relevant to widgets. ”
事件驱动是Qt体系中比信号和槽机制低一层级的信号响应机制。 比如鼠标事件/键盘事件/界面打开关闭都是在事件体系中完成。大部分事件处理在Qt体系已经定义好接口函数(常为虚函数),用户根据自己的处理目的不同对事件处理函数进行实现即可;当然也可以基于事件基类QEvent去开发自己的事件处理函数。 事件处理函数多为pretected大类的虚函数。
紧接着上一文的内容,继续通过代码来展示事件处理在Qt中的实现,此处主要基于QObject基类,所以能使用的事件函数不多。
QObject可以使用的事件虚函数三个:virtual void childEvent(QChildEvent *event) ,virtual void customEvent(QEvent *event) 和virtual void timerEvent(QTimerEvent *event) 。其中最常用的就是计时器事件处理函数timerEvent(QTimerEvent *event),后面就对这个函数进行讲解。
首先,要在头文件中重定义这个虚函数:
前面的virtual字样可以保留,比如以后需要继承该类再进行计时器事件函数重写。Override表示对虚函数进行重写。函数名称timerEvent和参数类型QTimerEvent *是一定不可修改的。
在源文件对其进行实现,目前还没有事件处理函数,所以只是建立代码开发的框架。最后的QObject::timerEvent(event)是事件处理函数的常用写法,如果此处不对计时器进行任何处理(或者已经处理结束),需要将事件处理权交给父类,也就是QObject。
下面构造一个简单的计时器场景,每隔一定的时间间隔调用setName()随机写入一个名字。要让计时器事件处理函数工作,需要定义一个计时器并启动起来。一种方法是新建一个QTimer对象来开始计时;QObject自带计时器,所以可以直接启动其计时器。在构造函数写入:
上面代码表示启动一个每隔1000ms触发一下的计时器。有了这个代码之后我们就可以在timerEvent()中监控计时器的工作。简单代码如下,打印出每次计时器工作的时间:
编译调试代码,在控制台显示每隔一秒的时间:
下面来实现刚才提到的调用setName函数随机写入一个名字,我们此处简单写一个方法QString newName = QString(“newName%1”).arg(qrand()%1001),利用随机数生成器qrand()生成一个0-1000之间的数,加到“newName “字符串后并赋值给newName,再将newName写入。 QString和qrand()与C++标准库中的字符串模板以及随机数生成器用法基本一样,可以自行查阅Qt帮助文本。
编译运行代码,看到控制台打印出m_nameVector列表中每隔一秒增加一个新的名字,而且相邻的名字不同。
事件处理是界面中必不可少的元素,比如鼠标拖拽/界面拉大缩小/快捷键等。如下面的常用事件处理虚函数接口,以QWidget为基类的所有类都可以对齐进行代码实现。关于QWidget的特征会在后面持续介绍。
virtual void actionEvent(QActionEvent *event)
virtual void changeEvent(QEvent *event)
virtual void closeEvent(QCloseEvent *event)
virtual void contextMenuEvent(QContextMenuEvent *event)
virtual void dragEnterEvent(QDragEnterEvent *event)
virtual void dragLeaveEvent(QDragLeaveEvent *event)
virtual void dragMoveEvent(QDragMoveEvent *event)
virtual void dropEvent(QDropEvent *event)
virtual void enterEvent(QEvent *event)
virtual void focusInEvent(QFocusEvent *event)
virtual void hideEvent(QHideEvent *event)
virtual void inputMethodEvent(QInputMethodEvent *event)
virtual void keyPressEvent(QKeyEvent *event)
virtual void keyReleaseEvent(QKeyEvent *event)
virtual void leaveEvent(QEvent *event)
virtual void mouseDoubleClickEvent(QMouseEvent *event)
virtual void mouseMoveEvent(QMouseEvent *event)
virtual void mousePressEvent(QMouseEvent *event)
virtual void mouseReleaseEvent(QMouseEvent *event)
virtual void moveEvent(QMoveEvent *event)
virtual bool nativeEvent(const QByteArray &eventType, void *message, long *result)
virtual void paintEvent(QPaintEvent *event)
virtual void resizeEvent(QResizeEvent *event)
virtual void showEvent(QShowEvent *event)
virtual void tabletEvent(QTabletEvent *event)
virtual void wheelEvent(QWheelEvent *event)
后期将继续介绍QObject的多线程体系,欢迎持续关注。本来打算近期再介绍一些关于QMetaObject的知识,但是这个难度实在是太大,笔者理论功底还不够,准备后期介绍。有这方面的大神,也请不吝赐教。
欢迎同好沟通交流,批评指正,欢迎关注我的公号:不如起而行之