zoukankan      html  css  js  c++  java
  • Day02_Qt消息机制与事件 (下)

     1、关于事件

          在之前的程序中已经使用过事件,例如在Qt程序的main()函数中创建一个应用对象QApplication,然后调用它的exec()函数,该exec()函数就是开始Qt的事件循环,在执行exec()函数之后,程序就会进入事件循环来监听应用程序的事件。当事件发生时,Qt将创建一个事件对象,Qt中所有事件都继承于QEvent,在事件对象创建完毕后,Qt将这个事件对象传递给QObject的event()函数。event()函数并不直接处理事件,而是根据事件对象的类型分派给特定的事件处理函数(Event handler)。

     

    事件处理函数为protected类型,为虚函数,举例:

    新建工程,基类为widget,在ui界面中添加label标签:

    之后在工程界面添加类文件,由于是添加Label的槽函数,而文件基类中没有Label基类,所以新建的文件基类选为QWidget,之后在生成的mylabel.h与myabel.cpp文件中将基类改为QLabel,.h与.cpp文件如图所示:

    #ifndef MYLABEL_H
    #define MYLABEL_H
    
    #include <QLabel>
    
    class MyLabel : public QLabel
    {
        Q_OBJECT
    public:
        explicit MyLabel(QWidget *parent = 0);
    protected:
        //鼠标按下事件
        void mousePressEvent(QMouseEvent *ev);
        //鼠标释放事件
        void mouseReleaseEvent(QMouseEvent *ev);
        //鼠标移动事件
        void mouseMoveEvent(QMouseEvent *ev);
    
         //鼠标进入窗口区域事件
        void enterEvent(QEvent *);
         //鼠标离开窗口区域事件
        void leaveEvent(QEvent *);
    
    signals:
    
    public slots:
    };
    
    #endif // MYLABEL_H

    mylabel.cpp文件为:

    #include "mylabel.h"
    #include<QMouseEvent>
    #include<QDebug>
    
    
    MyLabel::MyLabel(QWidget *parent) : QLabel(parent)
    {
    
    }
    //鼠标按下
    void MyLabel::mousePressEvent(QMouseEvent *ev)
    {
        int i=ev->x();
        int j=ev->y();
        //打印
        if(ev->button() == Qt::LeftButton)
        {
            qDebug() << "left";
        }
        else if(ev->button() == Qt::RightButton)
        {
            qDebug() << "right";
        }
        else if(ev->button() == Qt::MidButton)
        {
            qDebug() << "mid";
        }
    
        QString text=QString("<center><h1>Mouse Press:(%1,%2)</h1></center>").arg(i).arg(j);
    
        this->setText(text);
    
    }
    //鼠标释放
    void MyLabel::mouseReleaseEvent(QMouseEvent *ev)
    {
        QString text = QString("<center><h1>Mouse Release: (%1, %2)</h1></center>")
                .arg( ev->x() ).arg( ev->y() );
    
        this->setText(text);
    }
    
    //鼠标移动
    void MyLabel::mouseMoveEvent(QMouseEvent *ev)
    {
        QString text = QString("<center><h2>Mouse move: (%1, %2)</h2></center>")
                .arg( ev->x() ).arg( ev->y() );
    
         this->setText(text);
    }
    
    
    void MyLabel::enterEvent(QEvent *ev)
    {
        QString text = QString("<center><h1>Mouse enter</h1></center>");
    
        this->setText(text);
    }
    
    void MyLabel::leaveEvent(QEvent *ev)
    {
        QString text = QString("<center><h1>Mouse leave</h1></center>");
    
        this->setText(text);
    }

    为了使得鼠标在初始时即被跟踪,可以在mylabel.cpp的主函数main函数中添加:

    MyLabel::MyLabel(QWidget *parent) : QLabel(parent)
    {
        //设置追踪鼠标
         this->setMouseTracking(true);
    }

    之后在ui界面中选择label,将其进行提升,即可看到鼠标在移动、按下....的变化。

    2、事件的接收与忽略:

    2.1、以一个新的按钮为例,button,在button的槽函数,使用不同的返回语句会有不同的处理效果

    当返回语句为

      QPushButton::mousePressEvent(e);

     时,事件会返回到QPushButton的基类中,基类可以发出按键的clicked信号,进而对事件进行处理。处理函数为:

     //信号被上一级拦截,lambda表达式,需要在.pro文件中添加CONFIG +=C++11 

    connect(ui->pushButton, &MyButton::clicked, [=]() { qDebug() << "123"; } );

    可是采用ignore()作为返回函数时,

    e->ignore(); 

    事件传递到父组件,不是给父类(基类),所以处理函数是Widget下的处理函数。处理函数为:

    void MyWidget::mousePressEvent(QMouseEvent *e)
    {
        qDebug() << "+++++++++++++++++++++++";
    }

    所以,当事件发生后,如果要在事件处理完毕后进行下一级传递,需要将事件继续向下一级件传递,如果下一级的处理函数位于基类中,需要使用基类返回,如果位于父组件中,需要使用ignore()函数。

    3、事件event()

            事件对象创建完毕后,Qt会将这个对象传递给Obj的event()函数。event函数并不会直接处理函数,而是将这些事件根据不同的类型,分发给不同的事件处理器(Event Handler)在事件分发处理过程中常常使用到类型转换,如果希望在事件分发之前做一些操作,就可以重新event()函数,函数的返回类型为布尔类型。

    1. 如果传入的事件已被识别并处理,则需要返回true,佛则返回false,如果返回值是true,QT会认为这个事件已经处理完毕,不会再将这个事件发送给其他对象,而是继续处理事件队列中的下一事件
    2. 在event函数中,调用事件对象的accept和ignore是没有作用的,不会影响到事件的传播。我们处理完自己感兴趣的事件之后,可以直接调用父类的event()函数继续转发

    在下面的实例程序中,当事件的类型为定时器时,直接返回true代表定时器类型的事件处理完毕,即关闭定时器,如果把定时器部分的注释返回原型,即使得定时器正常工作,之后进行其他事件的处理。

    第二个if语句中处理的是按键事件,当按键是按下B时,按照原形式进行,其他形式直接返回true表示事件处理完毕。

    bool MyWidget::event(QEvent *e)
    {
    
        if(e->type() == QEvent::Timer)
        {
            //干掉定时器
            //如果返回true,事件停止传播
            //QTimerEvent *env = static_cast<QTimerEvent *>(e);
            //timerEvent(env);
            return true;
        }
        else if(e->type() == QEvent::KeyPress)
        {
            //类型转换
            QKeyEvent *env = static_cast<QKeyEvent *>(e);
            if(env->key() == Qt::Key_B)
            {
                return QWidget::event(e);
            }
            return true;
    
        }
        else
        {
            return QWidget::event(e);
            //return false;
        }
    
    }

    将事件转换为鼠标事件为例:

    事件处理器:evenFilter()函数
    函数声明:
     //事件过滤器
        bool eventFilter(QObject *obj, QEvent *e);   //过滤的控件----过滤的事件
    obj表示要过滤的控件,e表示要进行过滤的事件

    //在widget.cpp函数的主函数中添加一下语句方可使用过滤函数
      ui->label_2->installEventFilter(this);
    
    //函数定义
    
    bool MyWidget::eventFilter(QObject *obj, QEvent *e)
    {
        if(obj == ui->label_2)
        {
            QMouseEvent *env = static_cast<QMouseEvent *>(e);
            //判断事件
            if(e->type() == QEvent::MouseMove)
            {
                ui->label_2->setText(QString("Mouse move:(%1, %2)").arg(env->x()).arg(env->y()));
                return true;  //不要事件继续传播
            }
            if(e->type() == QEvent::MouseButtonPress)
            {
                ui->label_2->setText(QString("Mouse press:(%1, %2)").arg(env->x()).arg(env->y()));
                return true;
            }
            if(e->type() == QEvent::MouseButtonRelease)
            {
                ui->label_2->setText(QString("Mouse release:(%1, %2)").arg(env->x()).arg(env->y()));
                return true;
            }
            else
            {
                return QWidget::eventFilter(obj, e);
            }
        }
        else
        {
            return QWidget::eventFilter(obj, e);
        }
    }
    //类型转换
            QKeyEvent *env = static_cast<QKeyEvent *>(e);  
    要处理的事件类型为按键事件,所以需要将事件强制转换为 QKeyEvent *类型,该形式固定,
  • 相关阅读:
    Linq 中 表连接查询
    Html Div 拖拽
    持续集成:TestNG中case之间的关系
    测试技术培训:如何测试磁盘写的速度
    POPTEST 测试开发 免费培训课程报名
    接上文 下面是一段示例代码
    老李分享:android手机测试之适配(1)
    (转)POPTEST创始人李爱然:谢谢,帮助我的朋友!!!!
    性能调优之SQL优化
    大数据测试之Hadoop的基本概念
  • 原文地址:https://www.cnblogs.com/luxinshuo/p/12231775.html
Copyright © 2011-2022 走看看