事件(event)是由系统或者Qt本身在不同的时刻发出的。当用户按下鼠标,敲下键盘,或者是窗口需要重新绘制的时候,都会发出一个相应的事件。一些事件是当用户操作时做出响应发出,如键盘鼠标事件等;另外一些事件则是由系统自动发出,如计时器事件。
在前面我们也曾简单提到,Qt程序需要在main()函数创建一个QApplication 对象,然后调用它的exec()函数,这个函数就是开始Qt的事件循环。在执行exec()函数之后,程序将进入事件循环来监听应用程序的事件。当事件发生时,Qt将创建一个时间对象。Qt中所有事件类都继承于QEvent。在事件对象创建完毕之后,Qt将这个事件对象传递给Qobject的event()函数。event()函数并不直接处理事件。而是按照事件对象的类型分派给特定的事件处理函数(eventhandler)。
在所有组件的父类QWidget中,定义了很多事件处理的回调函数,如:
keyPressEvent()
keyReleaseEvent()
mouseDoubleClickEvent()等;
这些函数都是 protected virtual 的,也就是说,我们可以在子类中重新实现这些函数。
在了解以上的学习的内容后,我们现在要实现的功能描述如下:整体为两种事件,一种是外部触发事件,一种是内部事件(计数器)
定义一个窗口,里面添加一个QLabel控件,当鼠标按下的时候,能够显示其坐标,并且能够判断是鼠标的左键、右键、中间键。
首先需要重新定义一个MyQlabel 的类,继而在ui中进行提升,让在 ui 中的 label 控件的基类是MyLabel ,从而在程序的编写界面进行事件的处理。
项目的工程建立如下图:
ui界面文件如图:
mylabel.h文件:
#ifndef MYLABEL_H #define MYLABEL_H //#include <QWidget>//由于MyLabel继承于QLabel,所以这里需要将其修改为:#include<QLabel> #include<QLabel> //1 class MyLabel : public QLabel//2 { Q_OBJECT public: explicit MyLabel(QWidget *parent = 0); protected: /*这里需要说明一点,怎么知道虚函数有没有写错?这里的虚函数是保护类型的, * 当你忘记了事件的名字时,最好在QWidget中查看一下,值得一提的是事件代码: * void mousePressEvent(QMouseEvent *ev);中的任何一个都不能自己写,必须利用提示, * 这是因为如果是自己写的,就相当于自定义函数,就不是虚函数了。 * 并且,在mousePressEvent虚函数上按F1是没有反应的,必须在其基类QWidget中查看 */ //鼠标点击事件 void mousePressEvent(QMouseEvent *ev); //鼠标释放事件 void mouseReleaseEvent(QMouseEvent *ev); //鼠标移动事件 void mouseMoveEvent(QMouseEvent *ev); //进入窗口区域 void enterEvent(QEvent *); //离开窗口区域 void leaveEvent(QEvent *); signals: public slots: }; #endif // MYLABEL_H
mywidget.h:
#ifndef MYWIDGET_H #define MYWIDGET_H #include <QWidget> namespace Ui { class MyWidget; } class MyWidget : public QWidget { Q_OBJECT public: explicit MyWidget(QWidget *parent = 0); ~MyWidget(); protected: //键盘按下事件 void keyPressEvent(QKeyEvent *event); //计时器事件 void timerEvent(QTimerEvent *event); private: Ui::MyWidget *ui; int timeID ;//为了区分是哪一个计时器,添加计时器ID。 int timeID2; }; #endif // MYWIDGET_H
mylabel.cpp
#include "mylabel.h" #include <QMouseEvent> #include <QDebug> //3 MyLabel::MyLabel(QWidget *parent) : QLabel(parent) { //设置追踪鼠标,当鼠标一进来窗口就产生事件 this ->setMouseTracking(true); } void MyLabel::mousePressEvent(QMouseEvent *ev) { int i = ev->x(); int j = ev->y(); /*在这里,i和j都是整数类型。 * 在Qlabel上显示,需要将其进行格式化;这里介绍格式化的代码和arg的用法; * 例如:QString str = QString ("abc %1 ^_^ %2").arg(123).arg("mike"); * * 这里%1对应着第一个arg * %2对应着第二个arg * * 那么str就会变成: * str = abc 123 ^_^ mike * */ /* * 这个事件本身是当鼠标按下的时候会执行这里面的代码,为了更加的精确高级,还能判断是鼠标的左键,右键,中间键,从而更加精确的执行代码; */ if (ev->button() ==Qt::LeftButton) { qDebug()<<"鼠标的左键被按下!!!"; } else if (ev->button() == Qt::RightButton) { } else if (ev->button() ==Qt::MidButton) { } //这里添加的是H5代码 QString text = QString ("<center><h1>Mouse Press:(%1,%2)</h1></center>").arg(i).arg(j); this->setText(text); } void MyLabel::mouseReleaseEvent(QMouseEvent *ev) { } void MyLabel::mouseMoveEvent(QMouseEvent *ev) { } void MyLabel::enterEvent(QEvent *e) { QString text = QString ("<center><h1>Mouse enter</h1></center>"); this->setText(text); } void MyLabel::leaveEvent(QEvent *e) { }
mywidget.cpp:
#include "mywidget.h" #include "ui_mywidget.h" #include <QKeyEvent> #include <QDebug> MyWidget::MyWidget(QWidget *parent) : QWidget(parent), ui(new Ui::MyWidget) { ui->setupUi(this); //毫秒为单位,每隔1S触发一次定时器 timeID = this->startTimer(1000); timeID2 = this->startTimer(500); } MyWidget::~MyWidget() { delete ui; } //想知道怎么知道哪个按键被按下,可以对QKeyEvent按下F1,查看帮助文档 中的int key() const, void MyWidget::keyPressEvent(QKeyEvent *event) { qDebug()<<event->key();//直接打印ACSII码 qDebug()<<(char)event->key();//转化成字母打印出来 if(event->key() == Qt::Key_A) { qDebug()<<"Qt::Key_A"; } } void MyWidget::timerEvent(QTimerEvent *event) { if (event->timerId() == this->timeID) { static int sec = 0; ui->label->setText( QString ("<center><h1>time : %1</h1></center>").arg(sec++)); if (sec == 5) { this ->killTimer(this->timeID); } } else if (event->timerId() == this->timeID2) { static int sec = 0; ui->label_2->setText( QString ("<center><h1>time : %1</h1></center>").arg(sec++)); } }
至此为止,内部事件(计时器)和外部事件(鼠标和键盘)的功能就完成了。