目录
引言:
一、键盘事件
二、鼠标事件
三、定时器小实例
四、总结
QT程序是事件驱动的, 程序的每个动作都是由内部某个事件所触发。QT事件的发生和处理成为程序运行的主线,存在于程序整个生命周期。
常见的QT事件类型如下:
键盘事件: 按键按下和松开
鼠标事件: 鼠标移动,鼠标按键的按下和松开
拖放事件: 用鼠标进行拖放
滚轮事件: 鼠标滚轮滚动
绘屏事件: 重绘屏幕的某些部分
定时事件: 定时器到时
焦点事件: 键盘焦点移动
进入和离开事件: 鼠标移入widget之内,或是移出
移动事件: widget的位置改变
大小改变事件: widget的大小改变
显示和隐藏事件: widget显示和隐藏
窗口事件: 窗口是否为当前窗口
QT将系统产生的消息转化为QT事件,QT事件被封装为对象,所有的QT事件均继承抽象类QEvent,用于描述程序内部或外部发生的动作,任意的QObject对象都具备处理QT事件的能力。
头文件
#ifndef WIDGET_H
#define WIDGET_H
#include
#include
#include
#include
#include
#include
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
int nIdFast;
int nIdSlow;
public:
Widget(QWidget *parent = nullptr);
~Widget();
public:
//void closeEvent(QCloseEvent *event);
void keyPressEvent(QKeyEvent *event);
//void mousePressEvent(QMouseEvent *event);
//void timerEvent(QTimerEvent * event);
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
源文件
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//ui->pushButton->setText("close");
//ui->label->setText("哈哈");
nIdSlow = startTimer(1000);
nIdFast = startTimer(500);
//QObject::connect(ui->pushButton,&QPushButton::clicked,this,&QWidget::close);
QObject::connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(close()));
}
Widget::~Widget()
{
delete ui;
}
void Widget::closeEvent(QCloseEvent *event)
{
qDebug() << "close" << endl;
}
void Widget::keyPressEvent(QKeyEvent *event)
{
//ui->label->setText("呵呵");
switch(event->key())
{
case Qt::Key_A:
ui->label->setText("A");
break;
case Qt::Key_B:
ui->label->setText("B");
break;
}
}
运行:
头文件
#ifndef WIDGET_H
#define WIDGET_H
#include
#include
#include
#include
#include
#include
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
int nIdFast;
int nIdSlow;
public:
Widget(QWidget *parent = nullptr);
~Widget();
public:
//void closeEvent(QCloseEvent *event);
//void keyPressEvent(QKeyEvent *event);
void mousePressEvent(QMouseEvent *event);
//void timerEvent(QTimerEvent * event);
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
源文件
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//ui->pushButton->setText("close");
//ui->label->setText("哈哈");
nIdSlow = startTimer(1000);
nIdFast = startTimer(500);
//QObject::connect(ui->pushButton,&QPushButton::clicked,this,&QWidget::close);
QObject::connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(close()));
}
Widget::~Widget()
{
delete ui;
}
void Widget::mousePressEvent(QMouseEvent *event)
{
QString str;
int x = 0,y = 0;
if(event->button() == Qt::LeftButton)
{
x = event->x();
y = event->y();
str = "(" + QString::number(x) + "," + QString::number(y) + ")";
ui->label->setText(str);
}
if(event->button() == Qt::RightButton)
{
x = event->globalX();
y = event->globalY();
str = "(" + QString::number(x) + "," + QString::number(y) + ")";
ui->label->setText(str);
}
}
运行
头文件
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include
#include
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
int nIdFast1;
int nIdSlow1;
int nIdFast2;
int nIdSlow2;
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
public:
void keyPressEvent(QKeyEvent* event);
void timerEvent(QTimerEvent* event);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
源文件
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
nIdFast1 = startTimer(250);
nIdSlow1 = startTimer(1000);
nIdFast2 = startTimer(500);
nIdSlow2 = startTimer(1000);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::keyPressEvent(QKeyEvent* event)
{
switch(event->key())
{
case Qt::Key_A:
killTimer(nIdSlow1);
killTimer(nIdFast1);
ui->label_2->setText("A");
break;
case Qt::Key_B:
killTimer(nIdSlow2);
killTimer(nIdFast2);
ui->label->setText("B");
break;
case Qt::Key_C:
startTimer(250);
startTimer(1000);
ui->label_2->setText("C");
break;
case Qt::Key_D:
startTimer(500);
startTimer(1000);
ui->label->setText("D");
break;
}
}
void MainWindow::timerEvent(QTimerEvent* event)
{
static int n1 = 0;
static int x1 = 0;
if(event->timerId() == nIdSlow1)
{
n1++;
QString str = QString::number(n1);
ui->pushButton->setText(str);
}
if(event->timerId() == nIdFast1)
{
x1 += 5;
ui->pushButton->setGeometry(x1,100,50,50);
}
static int n2 = 0;
static int x2 = 0;
if(event->timerId() == nIdSlow2)
{
n2++;
QString str = QString::number(n2);
ui->pushButton_2->setText(str);
}
if(event->timerId() == nIdFast2)
{
x2 += 5;
ui->pushButton_2->setGeometry(x2,300,50,50);
}
}
运行
事件(event)是有系统或者 Qt 本身在不同的时刻发出的。当用户按下鼠标,敲下键盘,或者是窗口需要重新绘制的时候,都会发出一个相应的事件。一些事件是在对用户操作做出响应的时候发出,如键盘事件等;另一些事件则是由系统自动发出,如计时器事件。
一般来说,使用 Qt 编程时,我们并不会把主要精力放在事件上,因为在 Qt 中,需要我们关心的事件总会发出一个信号。比如,我们关心的是 QPushButton 的鼠标点击,但我们不需要关心这个鼠标点击事件,而是关心它的 clicked()信号。这与其他的一些框架不同:在 Swing 中,你所要关心的是JButton 的 ActionListener 这个点击事件。
Qt 的事件很容易和信号槽混淆。这里简单的说明一下,signal 由具体对象发出,然后会马上交给由connect 函数连接的 slot 进行处理;而对于事件,Qt 使用一个事件队列对所有发出的事件进行维护,当新的事件产生时,会被追加到事件队列的尾部,前一个事件完成后,取出后面的事件进行处理。但是,必要的时候,Qt 的事件也是可以不进入事件队列,而是直接处理的。并且,事件还可以使用“事件过滤器”进行过滤。总的来说,如果我们使用组件,我们关心的是信号槽;如果我们自定义组件,我们关心的是事件。因为我们可以通过事件来改变组件的默认操作。比如,如果我们要自定义一个 QPushButton,那么我们就需要重写它的鼠标点击事件和键盘处理事件,并且在恰当的时候发出 clicked()信号。
还记得我们在 main 函数里面创建了一个 QApplication 对象,然后调用了它的 exec()函数吗?其实,这个函数就是开始 Qt 的事件循环。在执行 exec()函数之后,程序将进入事件循环来监听应用程序的事件。当事件发生时,Qt 将创建一个事件对象。Qt 的所有事件都继承于 QEvent 类。在事件对象创建完毕后,Qt 将这个事件对象传递给 QObject 的 event()函数。event()函数并不直接处理事件,而是按照事件对象的类型分派给特定的事件处理函数(event handler)。关于这一点,我们会在以后的章节中详细说明。
在所有组件的父类 QWidget 中,定义了很多事件处理函数,如 keyPressEvent()、keyReleaseEvent()、mouseDoubleClickEvent()、mouseMoveEvent ()、mousePressEvent()、mouseReleaseEvent()等。这些函数都是 protected virtual 的,也就是说,我们应该在子类中重定义这些函数。