事件概述

 信号就是事件的一种,事件由用户触发;

鼠标点击窗口,也可以检测到事件;产生事件后,传给事件处理,判断事件类型,后执行事件相应函数;

类似单片机的中断(中断向量);

事件实验

工程准备

创建Qwidget基类工程且带UI

ui添加一个标签,这个标签拉得足够大,因为要显示

添加一个类文件Qwidget基类型的

更换为QLabel的基类

QT5之事件——包含提升控件-LMLPHP

QT5之事件——包含提升控件-LMLPHP

添加虚拟函数,属于保护类型;

输入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);//设置标签内容为str
   qDebug()<<str;
}

void MyLable::mouseReleaseEvent(QMouseEvent *ev)
{

}

void MyLable::mouseMoveEvent(QMouseEvent *ev)
{



}


<center>     </center>    //居中指令  后面加的 /属于闭合标记,相当于括号的最后一半括号

<h1>     </h1>  //加粗指令      后面加的 /属于闭合标记,相当于括号的最后一半括号

 %1 %2 属于参数 1 和参数2; .arg(i) .arg(j) //添加对应变量

类提升

QT5之事件——包含提升控件-LMLPHP

之前的标签基类,就变成了代码标签基类;

这个标签就成为了代码写的那个标标签;就可以显示文字了;

没有这个提升,就意味标签类不同,代码和UI的标签不是一个标签;

QT5之事件——包含提升控件-LMLPHP

按键事件+定时器事件

开始一个定时器,分辨率为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_OBJECT

public:
    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放一个按钮提升类

QT5之事件——包含提升控件-LMLPHP

设计一个按键和处理信号,和一个事件

实验结果:connet按键的信号相当于一个按下事件,但是被鼠标事件占用了,所以按键的信号等不到了;

所以按键connet的事件是等待不到的,事件被使用具有消耗性;

如下是按键的鼠标按下事件

QT5之事件——包含提升控件-LMLPHP

如下是按键按下信号和槽

按钮按下相当于事件。但是鼠标按下事件已经接受;所以传递不了给下方这个了;

所以下方无法被打印

QT5之事件——包含提升控件-LMLPHP

事件传递只能传递给父类组件(父类窗口)

使用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);//转发事件,继续下流事件
    }
   
    
}

事件分发和过滤之间的关系:

QT5之事件——包含提升控件-LMLPHP

过滤器

过滤器好处:不用单独给某个控件写事件分配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是当前被转化数据;

05-04 13:57