当前位置: 首页 > article >正文

Qt 5.14.2 学习记录 —— 십구 事件

文章目录

  • 1、事件的概念
  • 2、处理事件
  • 3、鼠标事件
    • 1、鼠标单击和双击
    • 2、鼠标移动
    • 3、鼠标滚轮滚动
  • 4、键盘事件
  • 5、定时器事件
  • 6、窗口移动和大小改变事件


1、事件的概念

用户进行操作时会产生事件,事件可以关联处理函数。Qt封装了操作系统的事件机制,然后进一步封装得到了信号槽。事件是信号槽的底层机制。如果一个行为在Qt中没有对应的信号,那么就需要重写事件处理函数。事件处理函数都是虚函数,这样才能被重写。关于事件处理函数,看Qt文档。

在这里插入图片描述

QEvent就是事件,下面则是各种子事件。一部分常见事件:

在这里插入图片描述

事件分发,事件过滤属于Qt事件机制底层的逻辑,Qt对此给程序员提供了一些API可用。

事件分发重写event函数,能获取所有事件,但这样程序员有可能因此出现大错误。

事件过滤顾名思义,它是事件分发的其中一步操作,它针对的是某一类型的时间。

2、处理事件

处理也就是写处理函数。重写事件处理函数,也就利用了多态机制。创建子类,继承自Qt自带的类,在子类中重写父类的事件处理函数。

处理鼠标进入和鼠标离开事件

创建一个QWidget项目,放一个label到界面,接下来的程序在鼠标进入label区域时label文本显示鼠标进入,离开时显示鼠标离开。可以把label的frameShape属性改为Box,方便观察。

在当前项目下,创建一个C++类,继承自QLabel。

在这里插入图片描述

在label.h文件中引入QLabel头文件。

// label.h

#include <QWidget>
#include <QLabel>

class Label : public QLabel
{
    Q_OBJECT
public:
    Label(QWidget* parent);
    
    void enterEvent(QEvent* event);
    void leaveEvent(QEvent* event);
};


// label.cpp

#include "label.h"
#include <QDebug>

Label::Label(QWidget* parent) : QLabel(parent)
{

}

void Label::enterEvent(QEvent *event)
{
    (void) event;
    qDebug() << "enterEvent";
}

void Label::leaveEvent(QEvent *event)
{
    (void) event;
    qDebug() << "leaveEvent";
}

自定义的类是Label,但是界面中的label是QLabel的,所以现在这些处理函数还不起作用。解决办法就是右键label,提升为,按照自定义的类名和头文件名来填写,不选全局包含;点击添加,选中新添加的项,提升即可。

也可以不单独创建一个类,直接在Widget文件中写逻辑,那么此时就不是在label里事件发生时有处理,而是在Qt整个窗口内触发事件时都会被处理。

3、鼠标事件

在QWidget项目下,创建自定义类Label,还是用QLabel作为父类,在界面中创建一个label,提升为Label类的。

1、鼠标单击和双击

// label.h

#include <QWidget>
#include <QMouseEvent>

class Label : public QLabel
{
    Q_OBJECT
public:
    Label(QWidget* parent);
    
    // 鼠标左键右键滚轮触发
    void mousePressEvent(QMouseEvent* event);
};

// label.cpp

#include "label.h"
#include <QDebug>

Label::Label(QWidget* parent) : QLabel(parent)
{

}

void Label::mousePressEvent(QMouseEvent *event)
{
    // 两个方式
    // 以label对象左上角为原点
    qDebug() << event->x() << ", " << event->y();
    // 以屏幕左上角为原点
    qDebug() << event->globalX() << ", " << event->globalY();

    // Qt罗列了一些按键
    if (event->button() == Qt::LeftButton)
        qDebug() << "按下左键";
    else if (event->button() == Qt::RightButton)
        qDebug() << "按下右键";
}

抬起和双击

// label.h

void mouseReleaseEvent(QMouseEvent* event);
void mouseDoubleClickEvent(QMouseEvent* event);

// label.cpp

void Label::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
        qDebug() << "释放左键";
    else if (event->button() == Qt::RightButton)
        qDebug() << "释放右键";
}

void Label::mouseDoubleClickEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
        qDebug() << "双击左键";
    else if (event->button() == Qt::RightButton)
        qDebug() << "双击右键";
}

2、鼠标移动

// label.h

void mouseMoveEvent(QMouseEvent* event);

// label.cpp

void Label::mouseMoveEvent(QMouseEvent *event)
{
    qDebug() << event->x() << event->y();
}

但是实际运行后,不会打印,是因为鼠标只要一移动,会触发大量的鼠标移动事件,那么为了程序运行流畅,Qt默认不追踪这个事件,所以不会触发。解决办法就是解开这个限制即可

Label::Label(QWidget* parent) : QLabel(parent)
{
    this->setMouseTracking(true);
}

3、鼠标滚轮滚动

// label.h

// 通过delta()来获取这次鼠标滚轮滚了多远
#include <QWheelEvent>
public:
	void wheelEvent(QWheelEvent* event);
private:
	int total;

// label.cpp

Label::Label(QWidget* parent) : QLabel(parent)
{
    total = 0;
}

void Label::wheelEvent(QWheelEvent *event)
{
    //qDebug() << event->delta();
    // 计算总的滚动距离
    total += event->delta();
    qDebug() << total;
}

4、键盘事件

QWidget项目,这次不创建子类,直接在widget文件中写

// widget.h

#include <QWidget>
#include <QKeyEvent>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

    void keyPressEvent(QKeyEvent *event);

private:
    Ui::Widget *ui;
};

// widget.cpp
#include <QDebug>

void Widget::keyPressEvent(QKeyEvent *event)
{
    // 组合键, 用修饰符modifiers来获取
    // ctrl + a
    if (event->key() == Qt::Key_A && event->modifiers() == Qt::ControlModifier)
        qDebug() << "组合键ctrl + A";
    else if (event->key() == Qt::Key_A)
        qDebug() << "按下了A键";
    else qDebug() << event->key();
}

5、定时器事件

QTimer实现定时器功能,它的基础是QTimerEvent定时器事件。

QWidget项目,放一个LCD Numbers到界面中

// widget.h

void timerEvent(QTimerEvent* event);
int timerId;

// widget.cpp

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

    // 开启定时器事件
    // timerId身份标识, 类似于Linux文件标识符
    timerId = this->startTimer(1000);
}

void Widget::timerEvent(QTimerEvent *event)
{
    // 如果一个程序存在多个定时器, 那么每个定时器都会触发timerEvent函数
    if (event->timerId() != this->timerId) return ;
    int value = ui->lcdNumber->intValue();
    if (value <= 0)
    {
        this->killTimer(this->timerId);
        return ;
    }
    value -= 1;
    ui->lcdNumber->display(value);
}

6、窗口移动和大小改变事件

// widget.h

#include <QWidget>
#include <QMoveEvent>
#include <QResizeEvent>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

    void moveEvent(QMoveEvent* event);
    void resizeEvent(QResizeEvent* event);

private:
    Ui::Widget *ui;
};

// widget.cpp

#include <QDebug>

void Widget::moveEvent(QMoveEvent *event)
{
    qDebug() << "之前的位置: " << event->oldPos();
    qDebug() << "现在的位置: " << event->pos();
}

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

结束。


http://www.kler.cn/a/518091.html

相关文章:

  • 豆包MarsCode 蛇年编程大作战 | 高效开发“蛇年运势预测系统”
  • Effective C++读书笔记——item23(用非成员,非友元函数取代成员函数)
  • Redis实现,分布式Session共享
  • S4 HANA Tax相关的定价过程
  • c#使用log4Net配置日志文件
  • idea maven本地有jar包,但还要从远程下载
  • 使用ArcMap或ArcGIS Pro连接达梦数据库创建空间数据库
  • 为什么redis会开小差?Redis 频繁异常的深度剖析与解决方案
  • 【ARM】解决MDK在打开工程的时候提示CMSIS的版本不对问题
  • kettle从入门到精通 第九十一课 ETL之kettle http接口下载文件流
  • Java设计模式:结构型模式→桥接模式
  • LabVIEW太阳能照明监控系统
  • PCI 总线学习笔记(三)
  • Vue3笔记——(五)路由
  • Kubernetes v1.28.0安装dashboard v2.6.1(k8s图形化操作界面)
  • kettle经验篇:分享两个小白常见问题
  • 免费获得Photoshop等设计软件的机会
  • CF 420A.Start Up(Java实现)
  • 14-6-2C++的list
  • 基于 AI Coding 「RTC + STT」 Web Demo