1.事件
用户进行的各种操作,也会产生事件,程序员同样可以给事件关联上处理函数(处理的逻辑),当事件触发的时候就能够执行到对应的代码。事件本身是操作系统提供的机制.Qt也同样把操作系统事件机制进行了封装,拿到了Qt中,但是由于事件对应的代码编写起来不是很方便,Qt对于事件机制又进行了进一步的封装,就得到了信号槽。
信号槽就是对于事件的进一步封装,事件是信号槽的底层机制
实际Qt开发程序过程中,绝大部分和用户之间进行的交互都是通过"信号槽”来完成的,有些特殊情况下,信号槽不一定能搞定(某个用户的动作行为,Qt没有提供对应的信号),此时就需要通过重写事件处理函数的形式,来手动处理事件的响应逻辑
事件是应用程序内部或者外部产生的事情或者动作的统称。在Qt中使用一个对象来表示一个事件。所有的Qt事件均继承于抽象类QEvent.。事件是由系统或者Qt平台本身在不同的时刻发出的。当用户按下鼠标、敲下键盘,或者是窗口需要重新绘制的时候,都会发出一个相应的事件。一些事件是在用户操作时发出,如键盘事件、鼠标事件等,另一些事件则是由系统本身自动发出,如定时器事件。常见的Qt事件如下:
事件名称 | 描述 |
鼠标事件 | 鼠标左键、鼠标右键、鼠标滚轮,鼠标的移动,鼠标按键的按下和松开 |
键盘事件 | 按键类型、按键按下、按键松开 |
定时器事件 | 定时时间到达 |
进入离开事件 | 鼠标的进入和离开 |
滚轮事件 | 鼠标滚轮滚动 |
绘屏事件 | 重绘屏幕的某些部分 |
显示隐藏事件 | 窗口的显示和隐藏 |
移动事件 | 窗口位置的变化 |
窗口事件 | 是否为当前窗口 |
大小改变事件 | 窗口大小改变 |
焦点事件 | 键盘焦点移动 |
拖拽事件 | 用鼠标进行拖拽 |
①重写event
函数
实现一个效果,鼠标进入label区域后打印eventLabel
,出去该区域后打印leaveLabel
在.ui
文件中创建一个Label,然后新建C++->class
,class名称为Label,父类为QLabel,勾选include QWidget,头文件为label.h
,在label.h
中,因为要使用自定义类,所以修改原来的Label();
为Label(QWidget* parent);
,修改label.cpp
中Label::Label(){}
为Label::Label(QWidget* parent):QLabel(parent){}
,然后在label.h
中创建函数void enterEvent(QEvent* event); void leaveEvent(QEvent* event);
(重写的时候,确保函数名字和函数的参数列表完全一致,形参名无所谓),在label.cpp
中实现终端打印。但是此刻.ui
文件中依然使用的原来的QLabel
,右击改控件,选择提升为,提升类名称为自己自定义的类名称,点击添加,然后提升
,此时改label控件才与我们写的自定义类关联了起来
#ifndef LABEL_H
#define LABEL_H
#include<QLabel>
#include <QWidget>
class Label : public QLabel
{
Q_OBJECT
public:
Label(QWidget* parent);
//重写的时候,确保函数名字和函数的参数列表完全一致,形参名无所谓
void enterEvent(QEvent* event);
void leaveEvent(QEvent* event);
};
#endif // LABEL_H
#include "label.h"
#include<QDebug>
Label::Label(QWidget* parent):QLabel(parent)
{
}
void Label::enterEvent(QEvent *event)
{
qDebug() << "enterEvent"<<endl;
}
void Label::leaveEvent(QEvent *event)
{
qDebug() << "LeaveEvent"<<endl;
}
②重写事件函数(按键、鼠标、滚轮、键盘、定时器)
整体过程跟上述基本一致,代码实现不同,具体有
1>(左键,右键,单击,释放,双击,释放)
#include "label.h"
#include<QDebug>
#include<QMouseEvent>
Label::Label(QWidget* parent):QLabel(parent)
{
}
void Label::mousePressEvent(QMouseEvent *ev)
{
if(ev->button() == Qt::LeftButton)
{
qDebug()<<"按下左键";
}
else if(ev->button() == Qt::RightButton)
{
qDebug()<<"按下右键";
}
//当前event对象包含了鼠标点击位置的坐标
qDebug()<<ev->x()<<','<< ev->y();
//globalX和globalY是以屏幕左上角为原点获取的坐标
qDebug()<<ev->globalX()<<','<< ev->globalY();
qDebug() << "---------" ;
}
void Label::mouseReleaseEvent(QMouseEvent *ev)
{
if(ev->button() == Qt::LeftButton)
{
qDebug() <<"左键释放";
qDebug() << "---------" ;
}
else if(ev->button() == Qt::RightButton)
{
qDebug() <<"右键释放";
qDebug() << "---------" ;
}
}
void Label::mouseDoubleClickEvent(QMouseEvent *ev)
{
if(ev->button() == Qt::LeftButton)
{
qDebug() << "-----双击左键----" ;
}
else if(ev->button() == Qt::RightButton)
{
qDebug() << "-----双击右键----" ;
}
}
2>鼠标位置以及滚轮事件
#include "widget.h"
#include "ui_widget.h"
#include<QDebug>
#include<QMouseEvent>
#include<QWheelEvent>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//把这个选项设置为true,才能追踪鼠标,设置为false的话,默认点击的时候才会追踪鼠标
//this->setMouseTracking(true);//慎用
total = 0;
}
Widget::~Widget()
{
delete ui;
}
void Widget::mouseMoveEvent(QMouseEvent *event)
{
qDebug() << event->x() << "," << event->y();
}
void Widget::wheelEvent(QWheelEvent *event)
{
total+=event->delta();
qDebug() << event->delta();
qDebug() << total;
qDebug() << "-------------";
}
3>键盘按键事件
#include "widget.h"
#include "ui_widget.h"
#include<QDebug>
#include<QKeyEvent>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::keyPressEvent(QKeyEvent *event)
{
// qDebug() << event->key();
if(event->key() == Qt::Key_A)
{
qDebug() << "按下A键有效";
}
if(event->key() == Qt::Key_B && event->modifiers() == Qt::ControlModifier)
{
qDebug() << "按下ctrl+B键有效";
}
}
4>定时器
Qt中在进行窗口程序的处理过程中,经常要周期性的执行某些操作,或者制作一些动画效果,使用定时器就可以实现。所谓定时器就是在间隔一定时间后,去执行某一个任务。定时器在很多场景下都会使用到,如弹窗自动关闭之类的功能等。
Qt中的定时器分为QTimerEvent
和QTimer
这2个类。
QTimerEvent
类用来描述一个定时器事件。在使用时需要通过startTimer()函数来开启一个定时器,这个函数需要输入一个以毫秒为单位的整数作为参数来表明设定的时间,它返回的整型值代表这个定时器。当定时器溢出时(即定时时间到达)就可以在timerEvent()函数中获取该定时器的编号来进行相关操作。QTimer
类来实现一个定时器,它提供了更高层次的编程接口,如:可以使用信号和槽,还可以设置只运行一次的定时器。
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//开启定时器事件
//timerId类似于文件描述符,是定时器的身份标识
timerId = this->startTimer(1000);
}
Widget::~Widget()
{
delete ui;
}
void Widget::timerEvent(QTimerEvent *event)
{
//如果程序中存在多个定时器(startTimer创建的定时器),此时每个定时器都会触发timerEvent函数
//先判定一下爱这次触发是否是想要的定时器触发的
if(event->timerId() != this->timerId)
{
//如果不是我们的定时器就直接忽略
//当前程序中只有一个定时器
return;
}
int value = ui->lcdNumber->intValue();
if(value <= 0)
{
//停止定时器
this->killTimer(this->timerId);
return;
}
value -= 1;
ui->lcdNumber->display(value);
}
5>窗口移动事件
#include "widget.h"
#include "ui_widget.h"
#include<QDebug>
#include<QMoveEvent>
#include<QResizeEvent>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::moveEvent(QMoveEvent *event)
{
qDebug() << event->pos();
}
void Widget::resizeEvent(QResizeEvent *event)
{
qDebug() << event->size();
}