QT 事件 Event 应用

一、事件处理过程

1. QT 事件应用介绍

众所周知Qt是一个基于C++的框架,主要用来开发带窗口的应用程序(不带窗口的也行,但不是主流)。
我们使用的基于窗口的应用程序都是基于事件,其目的主要是用来实现回调(因为只有这样程序的效率才是最高的)。所以在Qt框架内部为我们提供了一些列的事件处理机制,当窗口事件产生之后,事件会经过: 事件派发 -> 事件过滤->事件分发->事件处理 几个阶段。
Qt窗口中对于产生的一系列事件都有默认的处理动作,如果我们有特殊需求就需要在合适的阶段重写事件的处理动作,比如信号与槽就是一种事件(event)是由系统或者 Qt 本身在不同的场景下发出的。当用户按下/移动鼠标、敲下键盘,或者是窗口关闭/大小发生变化/隐藏或显示都会发出一个相应的事件。一些事件在对用户操作做出响应时发出,如鼠标/键盘事件等;另一些事件则是由系统自动发出,如计时器事件。
每一个Qt应用程序都对应一个唯一的 QApplication 应用程序对象,然后调用这个对象的 exec() 函数,这样Qt框架内部的事件检测就开始了( 程序将进入事件循环来监听应用程序的事件 )。

2. 事件分发过程

示例:

 int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

事件在Qt中产生之后的分发过程是这样的:

  1. 当事件产生之后,Qt使用用应用程序对象调用 notify() 函数将事件发送到指定的窗口:
[override virtual] bool QApplication::notify(QObject *receiver, QEvent *e);
  1. 事件在发送过程中可以通过事件过滤器进行过滤,默认不对任何产生的事件进行过滤。
// 需要先给窗口安装过滤器, 该事件才会触发
[virtual] bool QObject::eventFilter(QObject *watched, QEvent *event)
  1. 当事件发送到指定窗口之后,窗口的事件分发器会对收到的事件进行分类:
[override virtual protected] bool QWidget::event(QEvent *event);
  1. 事件分发器会将分类之后的事件(鼠标事件、键盘事件、绘图事件。。。)分发给对应的事件处理器函数进行处理,每个事件处理器函数都有默认的处理动作(我们也可以重写这些事件处理器函数),比如:鼠标事件:
// 鼠标按下
[virtual protected] void QWidget::mousePressEvent(QMouseEvent *event);
// 鼠标释放
[virtual protected] void QWidget::mouseReleaseEvent(QMouseEvent *event);
// 鼠标移动
[virtual protected] void QWidget::mouseMoveEvent(QMouseEvent *event);

二、重写事件案例

1. 鼠标事件

示例:程序关闭之前的询问,鼠标进入,鼠标离开,窗口大小改变。
widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    void enterEvent(QEvent *event) override;
    void leaveEvent(QEvent *event) override;
    void closeEvent(QCloseEvent *event) override;
    void wheelEvent(QWheelEvent *event) override;
    void resizeEvent(QResizeEvent *event) override;

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QCloseEvent>
#include <QDebug>
#include <QMessageBox>

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

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

void Widget::enterEvent(QEvent *)
{
    qDebug() << "mouse enter";
}

void Widget::leaveEvent(QEvent *)
{
    qDebug() << "mouse leave";
}

void Widget::wheelEvent(QWheelEvent *)
{
    qDebug() << "wheel leave";
}

void Widget::resizeEvent(QResizeEvent *event)
{
    qDebug() << "oldSize:" << event->oldSize()
    << "newSize:" << event->size();
}

void Widget::closeEvent(QCloseEvent *event)
{
    int ret = QMessageBox::warning(this, tr("My Application"),
                                   tr("close the window"),
                                   QMessageBox::Ok | QMessageBox::No);
    switch (ret) {
        case QMessageBox::Ok:
            event->accept();
        break;
        case QMessageBox::No:
            event->ignore();
        break;
    }
}

程序运行结果:
在这里插入图片描述

2. 自定义按钮事件

示例:点击图片按钮,实现不同图片显示。
添加按钮类:
在这里插入图片描述
添加图片:
在这里插入图片描述
在这里插入图片描述
添加了三张图片:
在这里插入图片描述
ui界面设置:
在这里插入图片描述
在这里插入图片描述

mybutton.h

#ifndef MYBUTTON_H
#define MYBUTTON_H

#include <QWidget>

class MyButton : public QWidget
{
    Q_OBJECT
public:
    explicit MyButton(QWidget *parent = nullptr);

private:
    QPixmap pic;

protected:
    void enterEvent(QEvent *event) override;
    void leaveEvent(QEvent *event) override;
    void mousePressEvent(QMouseEvent *event) override;
    void paintEvent(QPaintEvent *event) override;
signals:
    void clicked();
};

#endif // MYBUTTON_H

mybutton.cpp

#include "mybutton.h"

#include <QPainter>

MyButton::MyButton(QWidget *parent) : QWidget(parent)
{
    pic.load(":/o1.png");
    setFixedSize(pic.size());
    update();
}

void MyButton::enterEvent(QEvent *event)
{
    pic.load(":/o3.png");
    update();
}

void MyButton::leaveEvent(QEvent *event)
{
    pic.load(":/o1.png");
    update();
}

void MyButton::mousePressEvent(QMouseEvent *event)
{
    pic.load(":/o2.png");
    update();
    emit clicked();
}


void MyButton::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.drawPixmap(rect(), pic);
}

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    connect(ui->mybtn, &MyButton::clicked, [=](){
        qDebug() << "clicked";
    });
}

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

程序运行结果:
在这里插入图片描述

3. 实现字体缩放事件

示例:实现按 ctrl + 滚轮 实现文本字体缩放
添加一个文本编辑类:
在这里插入图片描述
提升定义的类:
在这里插入图片描述
mytextedit.h

#ifndef MYTEXTEDIT_H
#define MYTEXTEDIT_H

#include <QTextEdit>

class MyTextEdit : public QTextEdit
{
public:
    MyTextEdit(QWidget *parent);
    
protected:
    void wheelEvent(QWheelEvent *e) override;
    void keyPressEvent(QKeyEvent *e) override;
    void keyReleaseEvent(QKeyEvent *e) override;
    
private:
    bool ctrlKeyPressed = 0;
};

#endif // MYTEXTEDIT_H

mytextedit.cpp

#include "mytextedit.h"
#include "widget.h"

#include <QWheelEvent>
#include <QDebug>

MyTextEdit::MyTextEdit(QWidget *parent) : QTextEdit(parent)
{

}

void MyTextEdit::wheelEvent(QWheelEvent *e)
{
    if(ctrlKeyPressed == 1){
        if(e->angleDelta().y() > 0)
        {
            zoomIn();
        }
        else if(e->angleDelta().y() < 0)
        {
            zoomOut();
        }
        e->accept();
    }
    else
    {
        QTextEdit::wheelEvent(e);
    }

}

void MyTextEdit::keyPressEvent(QKeyEvent *e)
{
    if(e->key() == Qt::Key_Control)
    {
        qDebug() << "ctrl Pressed";
        ctrlKeyPressed = 1;
    }
    QTextEdit::keyPressEvent(e);
}

void MyTextEdit::keyReleaseEvent(QKeyEvent *e)
{
    if(e->key() == Qt::Key_Control)
    {
        qDebug() << "ctrl Release";
        ctrlKeyPressed = 0;
    }
    QTextEdit::keyPressEvent(e);
}

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    void zoomIn();

    void zoomOut();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"

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

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

void Widget::zoomIn()
{
    // 获得当前字体信息
    QFont font = ui->textEdit->font();
    // 获得字体大小
    int fontsize = font.pointSize();
    if (-1 == fontsize)
    {
        return;
    }

    // 改变并设置大小
    int newFontSize = fontsize + 1;
    font.setPointSize(newFontSize);
    ui->textEdit->setFont(font);
}

void Widget::zoomOut()
{
    // 获得当前字体信息
    QFont font = ui->textEdit->font();
    // 获得字体大小
    int fontsize = font.pointSize();
    if (-1 == fontsize)
    {
        return;
    }

    // 改变并设置大小
    int newFontSize = fontsize - 1;
    font.setPointSize(newFontSize);
    ui->textEdit->setFont(font);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

热爱嵌入式的小佳同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值