18黑马QT笔记之事件(包括事件上下)

18黑马QT笔记之事件(包括事件上下)

1 事件:
事件(event)是由系统或者 Qt 本身在不同的时刻发出的。当用户按下鼠标、敲下键盘,或者是窗口需要重新绘制的时候,都会发出一个相应的事件。一些事件在对用户操作做出响应时发出,如键盘事件等;另一些事件则是由系统自动发出,如计时器事件。
在前面我们也曾经简单提到,Qt 程序需要在main()函数创建一个QApplication对象,然后调用它的exec()函数。这个函数就是开始 Qt 的事件循环。在执行exec()函数之后,程序将进入事件循环来监听应用程序的事件。当事件发生时,Qt 将创建一个事件对象。Qt 中所有事件类都继承于QEvent。在事件对象创建完毕后,Qt 将这个事件对象传递给QObject的event()函数。event()函数并不直接处理事件,而是按照事件对象的类型分派给特定的事件处理函数(event handler),关于这一点,会在后边详细说明。

即上面的意思是,根据主函数的代码,主窗口显示后,exec()被调用代表进入事件循环,等待用户操作。 当用户触发某一个事件,Qt会创建一个具体事件的对象,产生该对象的具体类继承于基类QEvent。然后对象传递给QObject的event()函数,event()函数并不直接处理事件,而是按照事件对象的类型分派给特定的事件处理函数。

在所有组件的父类QWidget中,定义了很多事件处理函数,这些函数都是 protected virtual 的,也就是说,我们可以在子类中重新实现这些函数,进而当事件触发时,它的处理结果可以按照我们想要的方式实现。
1)keyPressEvent(); //键盘按下 (标签内重写按下键盘无反应因为标签用于显示不能再接收键盘修改)
2)keyReleaseEvent(); //键盘/释放 键盘事件处理函数一般在窗口中重写 即上面的也是
3)mouseDoubleClickEvent(); //鼠标双击 鼠标事件重写函数一般在自定义控件中重写
4)mouseMoveEvent(); //鼠标移动
5)mousePressEvent(); //鼠标按下
6)mouseReleaseEvent() 。 //鼠标释放
7)void timerEvent(); //计时器重写事件处理函数 一般也在窗口显示

看图理解上面的内容:

在这里插入图片描述

下面我们例举一个例子来重写这些事件处理函数:

例子1:用一个标签,重写它的鼠标按下,释放、移动,进入、离开五个事件处理函数。
1)首先,我们创建完带ui的项目后,由于我们要重写标签的事件处理函数,所以我们需要再添加一个自定义控件类MyLabel。
创建自定义控件方法:右击项目添加新文件,继承QWidget先,然后将构造函数和主函数的父类改成继承于QLabel,最后在ui界面右击点击"提升为"即可,这样你选择提升的控件就是你自己定义的新控件了。自定义控件的创建基本都是这样。注意你的具体控件名别与自定义类的名字重名,否则出错,即ui右上角的对象与类。

2)代码(在自定义控件重写这五个事件处理函数):
这里只给出自定义控件的头文件和实现文件:
1)头文件.h:

#ifndef MYLABEL_H
#define MYLABEL_H

#include <QWidget>
#include<QLabel>

class MyLabel : public QLabel
{
    Q_OBJECT
public:
    explicit MyLabel(QWidget *parent = 0);

    //重写自定义控件的数据处理函数  与重写event()一样 都是在类中写
    //注意:在虚函数按fn+f1查看帮助文档是没有内容的 必须到基类才有 例如QWidget
    void mouseMoveEvent(QMouseEvent *ev);
    void mousePressEvent(QMouseEvent *ev);
    void mouseReleaseEvent(QMouseEvent *ev);
    void enterEvent(QEvent *event);
    void leaveEvent(QEvent *event);
    //这里重写键盘按下事件处理函数 没有反应以后需要注意


signals:

public slots:
};

#endif // MYLABEL_H

2)实现文件.cpp(包含文档内容和视频内容):

#include "mylabel.h"
#include<QMouseEvent>
#include<QDebug>

MyLabel::MyLabel(QWidget *parent) : QLabel(parent)
{
    //设置追踪鼠标 即一开始不用按下就可以追踪显示  这句话写在哪里区别不大
    this->setMouseTracking(true);
}


//重写事件处理函数之鼠标按下
void MyLabel::mousePressEvent(QMouseEvent *event)
{
    /*文档内容
    this->setText(QString("<center><h1>Press:(%1, %2)</h1></center>").arg(QString::number(event->x()),
                  QString::number(event->y())));
    */

    //视频内容
    //获取鼠标按下时 触发的对象的坐标
    int i = event->x();
    int j = event->y();
    /* QString的使用方法:用惯这种形式(上面不是很熟悉 上面的arg直接使用两个参数)
     * QString str = QString("abc %1 ^_^ %2").arg("123").arg("mike");
     * str = abc 123 ^_^ mike
    */

    //如果是左键按下
    if(event->button() == Qt::LeftButton)
    {
        qDebug() << "left";
    }
    else if(event->button() == Qt::RightButton)
    {
        qDebug() << "right";
    }
    else if(event->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 *event)
{
    /*文档内容
    QString msg;
    //使用Qt的sprintf拼接字符串 上面使用的是QString(QString("%1,%2")).arg(1).arg(2)的形式
    msg.sprintf("<center><h1>Release: (%d, %d)</h1></center>",event->x(), event->y());
    this->setText(msg);
    */

    //视频内容
    QString text = QString("<center><h1>Mouse Release: (%1, %2)</h1></center>").arg(event->x()).arg(event->y());
    this->setText(text);


}

//重写事件处理函数之鼠标移动
void MyLabel::mouseMoveEvent(QMouseEvent *event)
{
    /*文档内容
    //this代表MyLabel控件了  不是窗口
    this->setText(QString("<center><h1>Move: (%1, %2)</h1></center>").arg(QString::number(event->x()),
                  QString::number(event->y())));
    */

    //视频内容
    QString text = QString("<center><h1>Mouse move: (%1, %2)</h1></center>").arg(event->x()).arg(event->y());
    //this->setText(text);
}

//重写鼠标进入标签事件函数
void MyLabel::enterEvent(QEvent *event)
{
    //注:进入事件会被移动事件覆盖 所以想要显示需要注释移动的显示先
    QString text = QString("<center><h1>Mouse Enter</h1></center>");
    this->setText(text);
}

//重写鼠标离开标签事件函数
void MyLabel::leaveEvent(QEvent *event)
{
    QString text = QString("<center><h1>Mouse Leave</h1></center>");
    this->setText(text);
}

为什么要点击鼠标之后才能在mouseMoveEvent()函数中显示鼠标坐标值?
这是因为QWidget中有一个mouseTracking属性,该属性用于设置是否追踪鼠标。只有鼠标被追踪时,mouseMoveEvent()才会发出。如果mouseTracking是 false,组件在至少一次鼠标点击之后,才能够被追踪,也就是能够发出mouseMoveEvent()事件。如果mouseTracking为 true,则mouseMoveEvent()直接可以被发出。所以我们在MyLabel构造函数写下this->setMouseTracking(true);即可,位置没啥要求,写在主函数也行,但this需要改改。

例子2(在窗口中重写):
1)重写按键按下处理函数和定时器事件处理函数的头文件(窗口.h):

#ifndef MYWIDGET_H
#define MYWIDGET_H

#include <QWidget>
#include"mylabel.h"
#include<QTimerEvent>

namespace Ui {
class MyWidget;
}

class MyWidget : public QWidget
{
    Q_OBJECT

public:
    explicit MyWidget(QWidget *parent = 0);
    ~MyWidget();

protected:
    //重写键盘按下事件处理函数 --需要在窗口写  以后就可以避免错误
    void keyPressEvent(QKeyEvent *ev);
    //重写计时器事件处理函数   --注意  我在标签显示秒数  所以第一个标签所写的处理函数的显示会被覆盖 和进入被移动覆盖一样
    void timerEvent(QTimerEvent *event);

private:
    Ui::MyWidget *ui;
    int timerId1;     //定时器1、2的序号 相当于文件描述符
    int timerId2;


};

#endif // MYWIDGET_H

2)实现.cpp文件:

#include "mywidget.h"
#include "ui_mywidget.h"
#include<QDebug>
#include<QKeyEvent>
#include<QTimerEvent>

MyWidget::MyWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::MyWidget)
{
    ui->setupUi(this);

    //构造窗口时就让它开启定时器 开启内部就会自动计数 按规定时间触发事件 单位为毫秒 返回值为文件描述符(认为他是)
    timerId1=this->startTimer(1000);
    timerId2=this->startTimer(1000);

}

MyWidget::~MyWidget()
{
    delete ui;
}

//重写按键按下事件处理函数  --写在自定义标签不行  具体原因我也不知道  知道不行即可
void MyWidget::keyPressEvent(QKeyEvent *ev)
{
    qDebug()<<(char)ev->key();  //加不加char都只能显示大写或其ASCII码值

    if(ev->key()==Qt::Key_A)
    {
        qDebug()<<Qt::Key_A;
    }
}

//重写定时器事件处理函数
void MyWidget::timerEvent(QTimerEvent *event)
{
    //如果是定时器1 则让它在标签1每一秒显示一次 一共显示五次
    if(event->timerId()==timerId1)
    {
        //注意是static 否则每次都是显示0  这里的sec与下面的不一样 他们会开辟不同的内存
        static int sec=0;
        ui->MyLabel1->setText(QString("<center><h1>Timer:%1</h1></center>").arg(sec++));
        //显示五次后 停止定时器 利用文件描述符
        if(sec==5)
        {
            killTimer(timerId1);
        }
    }
    //如果是定时器2 让它一直显示
    if(event->timerId()==timerId2)
    {
        static int sec=0;
        ui->MyLabel2->setText(QString("<center><h1>Timer:%1</h1></center>").arg(sec++));
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值