事件概述
信号就是事件的一种,事件由用户触发;
鼠标点击窗口,也可以检测到事件;产生事件后,传给事件处理,判断事件类型,后执行事件相应函数;
类似单片机的中断(中断向量);
事件实验
工程准备
创建Qwidget基类工程且带UI
ui添加一个标签,这个标签拉得足够大,因为要显示
添加一个类文件Qwidget基类型的
更换为QLabel的基类
添加虚拟函数,属于保护类型;
输入void mousePressEvent(QMouseEvent *ev);如果参数不显示,删除括号且之后的删除;然后重新打括号
mylable.h
#ifndef MYLABLE_H
#define MYLABLE_H#include <QWidget>
#include<QLabel>
#include<QMouseEvent>
class MyLable : public QLabel
{Q_OBJECT
public:explicit MyLable(QWidget *parent = 0);
protected:void mousePressEvent(QMouseEvent *ev);void mouseReleaseEvent(QMouseEvent *ev);void mouseMoveEvent(QMouseEvent *ev);signals:public slots:
};#endif // MYLABLE_H
mylable.c
#include "mylable.h"
#include<QString>
#include<QDebug>
MyLable::MyLable(QWidget *parent) : QLabel(parent)
{this->setMouseTracking(true);//默认追踪鼠标,一开始不用点击窗口,就在追踪了
}void MyLable::mousePressEvent(QMouseEvent *ev)
{int i=ev->x();int j=ev->y();if(ev->button()==Qt::LeftButton)//左键{qDebug()<<"LeftButton";}else if(ev->button()==Qt::RightButton)//右键{qDebug()<<"RightButton";}else if(ev->button()==Qt::MidButton)//中间按键{qDebug()<<"MidButton";}//居中加粗指令QString str=QString("<center><h1>press mouse:(%1 ,%2)</h1></center>").arg(i).arg(j);this->setText(str);//设置标签内容为strqDebug()<<str;
}void MyLable::mouseReleaseEvent(QMouseEvent *ev)
{}void MyLable::mouseMoveEvent(QMouseEvent *ev)
{}
<center> </center> //居中指令 后面加的 /属于闭合标记,相当于括号的最后一半括号
<h1> </h1> //加粗指令 后面加的 /属于闭合标记,相当于括号的最后一半括号
%1 %2 属于参数 1 和参数2; .arg(i) .arg(j) //添加对应变量
类提升
之前的标签基类,就变成了代码标签基类;
这个标签就成为了代码写的那个标标签;就可以显示文字了;
没有这个提升,就意味标签类不同,代码和UI的标签不是一个标签;
按键事件+定时器事件
开始一个定时器,分辨率为1ms 返回一个定时器ID
//停止定时器,只能使用kill
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include "mylable.h"
#include<QKeyEvent>//按键事件头
#include<QDebug>
#include<QTimerEvent>//定时器事件头
Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);ID1_time =this->startTimer(1000);//开始一个定时器,分辨率为1ms 返回一个定时器ID
}Widget::~Widget()
{delete ui;
}void Widget::keyPressEvent(QKeyEvent *e)//按键事件处理函数
{qDebug()<< (char)e->key();//打印按键if(e->key()==Qt::Key_A)//按键时这个就打印{qDebug()<< "Qt::Key_A";}}void Widget::timerEvent(QTimerEvent *t)//定时器事件处理函数
{if(t->timerId()==ID1_time)//判断当前的ID{static int time_counter;qDebug()<< time_counter++;if(time_counter==10){this->killTimer(ID1_time);//停止定时器,只能使用kill}}
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include<QTimerEvent>
namespace Ui {
class Widget;
}class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent = 0);~Widget();protected://虚拟函数,都使用保护void keyPressEvent(QKeyEvent *e);//虚拟函数,按键事件void timerEvent(QTimerEvent *t);//虚拟函数,定时器事件private:Ui::Widget *ui;int ID1_time;//定时器ID
};#endif // WIDGET_H
按钮事件的接收和忽略
事件相当于信号量;使用就没有了;
新建一个类MyButton属于Qwidget基类;
把新建的构造函数和基类改成继承于QPushButton;
ui放一个按钮提升类
设计一个按键和处理信号,和一个事件
实验结果:connet按键的信号相当于一个按下事件,但是被鼠标事件占用了,所以按键的信号等不到了;
所以按键connet的事件是等待不到的,事件被使用具有消耗性;
如下是按键的鼠标按下事件
如下是按键按下信号和槽
按钮按下相当于事件。但是鼠标按下事件已经接受;所以传递不了给下方这个了;
所以下方无法被打印
事件传递只能传递给父类组件(父类窗口)
使用e->accept();//接收事件,事件不会向下传递
e->ignore();//忽略事件,事件会向下传递
代码设计为
按键的鼠标按下事件
void MyButton::mousePressEvent(QMouseEvent *e)
{if(e->button()== Qt::LeftButton){qDebug()<<"鼠标左按键被按下";e->ignore();//忽略事件,传递给父组件,也就是主窗口;//一般使用在关闭窗口,关闭窗口的时候,让事件传递;//没有ignore,也就是信号已经被这个处理,信号相当于信号量,使用就没有了}else//否则左键没被按下 ,不做处理{QPushButton::mousePressEvent(e);//没被按下,就传递给父组件}}
父类的鼠标按下
void Widget::mousePressEvent(QMouseEvent *e)
{qDebug()<<"+++++++++++++++++++";
}void Widget::closeEvent(QCloseEvent *e)
{int reg=QMessageBox::question(this,"question","是否需要关闭窗口");if(reg==QMessageBox::Yes){e->accept();//接收事件,事件不会向下传递}else{e->ignore();//忽略事件,事件会向下传递}}
event事件分发
事件分发分类分发给相应的事件处理函数;每个控件一个event。
在widget.h添加个
protected:
bool event(QEvent *e);//事件分发器 ,返回true就是说明事件已经被处理,停止向下传播
在widget.c分发器
bool Widget::event(QEvent *e)//
{//事件按照类型分发switch (e->type()) {case QEvent::Close:closeEvent(e);break;case QEvent::KeyPress:keyPressEvent(e);break;default:break;} ;if(e->type() == QEvent::Timer){QTimerEvent *env= static_cast<QTimerEvent * >(e);timerEvent( env);//处理定时事件 屏蔽这个,永远不会分发return true;//返回true 表明事件被处理}else if(e->type() == QEvent::KeyPress)//事件是按键类型{QKeyEvent *env=static_cast<QKeyEvent*>(e) ; if(env->key()==Qt::Key_B) {qDebug()<<"bbbbbBBBB";}}else{return QWidget::event(e);//转发事件,继续下流事件}}
事件分发和过滤之间的关系:
过滤器
过滤器好处:不用单独给某个控件写事件分配EVENT;在过滤器里面可以,写一个EVENT程序,同时给多个器件使用;
成员的保护类添加如下
bool eventFilter(QObject *obj, QEvent *e);//过滤器 过滤的obj控件 e过滤的事件
返回ture 就是停止过滤,过滤完成 ,flase 未过滤完成;
过滤器代码
bool Widget::eventFilter(QObject *obj, QEvent *e)
{if(obj== ui->pushButton)//这里可以并多个器件,相对写单个EVENT{if(e->type() == QEvent::MouseButtonPress){qDebug()<<" 鼠标被按下 ";//处理return true;//已经处理,不会继续传播}else{return QWidget::eventFilter(obj,e);//继续传播}}else{return QWidget::eventFilter(obj,e);//则继续传递下去}}
补充知识点:
类型转换:
QTimerEvent *env= static_cast<QTimerEvent* >(e);
static_castt< >转换指令 ,符号里面是需要转换成的目标类型,(e)中的e是当前被转化数据;