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

Qt系统相关——事件

文章目录

    • 事件和信号槽的关系
    • 事件处理
    • 鼠标事件
      • 鼠标进入和离开
      • 鼠标点击获取位置
      • 鼠标释放
      • 鼠标双击
      • 鼠标移动
      • 鼠标滚轮
    • 键盘事件
    • 定时器事件
    • 窗口移动和窗口改变

事件和信号槽的关系

Qt信号槽机制: 用户进行的操作就可能产生信号,可以给某个信号指定槽函数,当信号触发的时候,就能够执行到对应的槽函数。

对于事件,和信号槽类似,用户进行的各种操作,也会产生事件,可以给事件关联处理函数,当事件触发的时候,就能够执行到对应的代码。

事件本身是由操作系统提供的机制,Qt将操作系统事件机制进行封装。

但是事件对应的代码编写起来不方便,Qt对事件机制又继续了进一步封装,就得到了信号槽。

事件是信号槽的底层机制

大部分情况都是采用信号槽,但对于有些行为,Qt没有提供对应的信号,此时就需要重写事件处理函数,来手动处理事件的响应逻辑了。

事件机制,灵活度更高。

常见Qt事件:

image-20240922090528528

常见事件描述:

事件名称描述
鼠标事件鼠标左键、鼠标右键、鼠标滚轮、鼠标的移动、鼠标按键的按下和松开
键盘事件按键类型、按键按下、按键松开
定时器事件定时时间到达
进入离开事件鼠标的进入和离开
滚轮事件鼠标滚轮滚动
绘屏事件重绘屏幕的某些部分
显示隐藏事件窗口的显示和隐藏
移动事件窗口位置的变化
窗口事件是否为当前窗口
大小改变事件窗口大小改变
焦点事件键盘焦点移动
拖拽事件用鼠标进行拖拽

事件处理

事件处理就是让一段代码和某个事件关联起来,当事件触发的时候,就能指定到这段代码。

之前信号槽是通过connect来完成上述关联的;

对于事件,让当前的类,重写某个事件处理函数。

属于多态机制,创建子类,继承Qt自己的类,然后重新父类的事件处理函数。

鼠标事件

鼠标进入和离开

处理一下鼠标的进入和离开事件

image-20240922092214568

ui界面:

image-20240922093513461

创建QLabel的子类,然后重写enterEventleaveEvent

image-20240922094435747

label.h

#ifndef LABEL_H
#define LABEL_H

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

#endif // LABEL_H

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,而界面是的是QLabel

要确保界面上的label是我们自定义的实例,才会执行到这两个函数。

image-20240922095020397

GIF 2024-9-22 9-51-09

鼠标点击获取位置

image-20240922100213101

label.cpp

#include "label.h"
#include<QDebug>
#include<QMouseEvent>
Label::Label(QWidget* parent)
    :QLabel(parent)
{}

void Label::mousePressEvent(QMouseEvent *event)
{
    //当前控件左上角为原点
    qDebug() << event->x() << "," << event->y();
    //屏幕左上角为原点
    qDebug() << event->globalX() << "," << event->globalY();
}

GIF 2024-9-22 10-11-31

这个函数可以触发鼠标的各种按键,例如左键、右键、滚轮等

#include "label.h"
#include<QDebug>
#include<QMouseEvent>
Label::Label(QWidget* parent)
   :QLabel(parent)
{}

void Label::mousePressEvent(QMouseEvent *event)
{
   if(event->button() == Qt::LeftButton)
   {
       qDebug() << "左键触发"; 
   }
   else if(event->button() == Qt::RightButton)
   {
       qDebug() << "右键触发";	
   }
   //当前控件左上角为原点
   qDebug() << event->x() << "," << event->y();
   //屏幕左上角为原点
   qDebug() << event->globalX() << "," << event->globalY();
}

image-20240922114302874

鼠标释放

基于上面的代码,重写鼠标释放函数

image-20240922114904755

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

一次clicked,相当于鼠标一次按下事件+一次释放事件

鼠标双击

重写双击虚函数

image-20240922115103366

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

GIF 2024-9-22 11-55-06

这里双击的时候,也会触发单击的事件,这就又有可能导致意外的情况

鼠标移动

上面都是在Label控件里面进行活动,也可以直接放到Widget里面来完成。

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 mouseMoveEvent(QMouseEvent* event);

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

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include<QDebug>
#include<QMouseEvent>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}

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

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

上面的代码,不会直接移动的时候捕获位置,因为鼠标经常移动,稍微移动一下,就会产生大量的鼠标移动事件。

在捕获事件的时候,如果这里逻辑很复杂,就会导致程序特别卡顿。

为了保证程序流畅性,默认不会对鼠标移动进行追踪,鼠标移动的时候,不会调用mouseMoveEvent,除非显式告诉Qt

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

鼠标滚轮

通过wheelEvent

image-20240922144016520

#include "widget.h"
#include "ui_widget.h"
#include<QDebug>
#include<QMouseEvent>
#include<QWheelEvent>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    total = 0;
}

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

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

void Widget::wheelEvent(QWheelEvent *event)
{
    total += event->delta();
    qDebug() << total;
}

键盘事件

QShortCut定义一个快捷键,然后搭配QKeySequence这个类,指定当前按键是什么按键序列。如果按下这个键,就触发actived信号。这是信号槽机制封装过的,获取键盘按键的快捷方式。

也可以通过事件获取到当前用户键盘按下的情况。

重写一个父类函数,keyPressEvent

image-20240922145245623

单个按键:

#include "widget.h"
#include "ui_widget.h"
#include<QDebug>
#include<QKeyEvent>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}

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

void Widget::keyPressEvent(QKeyEvent *event)
{
    qDebug() << event->key();
}

组合按键:

image-20240922154253465

#include "widget.h"
#include "ui_widget.h"
#include<QDebug>
#include<QKeyEvent>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}

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

void Widget::keyPressEvent(QKeyEvent *event)
{
    if(event->key() == Qt::Key_A && event->modifiers() == Qt::ControlModifier)
    {
        qDebug() << "alt + A";
    }
}

定时器事件

可以使用QTimer这个类来完成定时器这个功能。

QTimer背后是QTimerEvent定时器事件来进行支撑;

QObject提供了timerevent这个函数:

  • startTimer启动定时器
  • killTimer关闭定时器

image-20240922155257245

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 timerEvent(QTimerEvent *event);
private:
    Ui::Widget *ui;
    int timerId;
};
#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);

    //开启定时器事件
    //startTimer由QObject提供
    //Widget继承QWidget
    //QWidget继承QObject

    //返回一个整数,定时器身份标识
    timerId = this->startTimer(1000);
}

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

void Widget::timerEvent(QTimerEvent *event)
{
    //一个程序存在多个定时器, 每个定时器都会触发这个函数
    //需要判断,这次触发是否是想要的定时器触发的
    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);
}

窗口移动和窗口改变

  • moveEvent窗口移动时触发的事件image-20240922155900630
  • resizeEvent窗口大小改变时触发的事件
    image-20240922160017780
#include "widget.h"
#include "ui_widget.h"
#include<QDebug>
#include<QMoveEvent>
#include<QResizeEvent>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}

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

void Widget::moveEvent(QMoveEvent *event)
{
    qDebug() << event->pos();
}

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

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

相关文章:

  • 干货分享之Python爬虫与代理
  • 算法每日双题精讲——滑动窗口(长度最小的子数组,无重复字符的最长子串)
  • 【C++学习(37)】并发性模式:如生产者-消费者、读写锁等。 架构模式:如MVC、MVVM等。属于23 种设计模式吗? RAII 的关系?
  • Vue2:组件
  • 开源模型应用落地-qwen模型小试-Qwen2.5-7B-Instruct-tool usage入门-Qwen-Agent深入学习(四)
  • StructuredStreaming (一)
  • JavaScript --模版字符串用反引号
  • Qt (19)【Qt 线程安全 | 互斥锁QMutex QMutexLocker | 条件变量 | 信号量】
  • python学习笔记(3)——控制语句
  • Java获取Object中Value的方法
  • 数据结构-3.链表
  • 无人机在隧道中如何实现在无卫星信号下的自主导航
  • 将ipad作为数位板使用教程/出现延迟拖拽怎么办?
  • 在jupyter notebook中取消代理服务器的解决方案
  • 编程遇到问题了?一个命令让 AI 解决你的困惑!
  • Android——内部/外部存储
  • HTTP常见状态码 HTTP的逐步发展(通俗易懂版)
  • 利士策分享,赚钱有道,底线思维不可抛
  • 网络安全-shire写任务计划、反弹shell、写私钥、反序列化
  • 机器学习算法与Python实战 | 三万字详解!GPT-5:你需要知道的一切(上)建议收藏!
  • 性能监控之Python实战SkyWalking链路追踪
  • [java][git]git学习
  • Linux动态库防止逆向编译参数
  • keil的debug功能
  • IT行业的未来:技术变革与创新的持续推动
  • 解决fatal: unable to access ‘https://........git/‘: Recv failure: Operation time