• QT学习_09_事件


    1、前言

    Qt 中所有事件类都继承于QEvent。 在事件对象创建完毕后,Qt 将这个事件对象传递给QObject的event()函数。event()函数并不直接处理事件,而是按照事件对象的类型分派给特定的事件处理函数(event handler),关于这一点,会在后边详细说明。

    在所有组件的父类QWidget中,定义了很多事件处理的回调函数,如

    1. keyPressEvent()
    2. keyReleaseEvent()
    3. mouseDoubleClickEvent()
    4. mouseMoveEvent()
    5. mousePressEvent()
    6. mouseReleaseEvent() 等。

    这些函数都是 protected virtual 的,也就是说,我们可以在子类中重新实现这些函数。

    重写的虚函数要按照它原来的定义的返回值 参数,要完全一样

    2、子控件的事件处理函数

    如果对一些子控件的某一些事件,比如QLabel QpushButton这些。

    最好自己构造一个 QLabel或者QpushButton的子类,然后在ui界面设计上把它提升,然后在子类中去写事件处理函数。

    下面以QLabel为例,创建一个子类

     

    先到 mylabel.h里面修改

    再到mylabel.cpp里面修改

     在ui设计界面中添加一个label控件

     

     

     这是点击了添加之后的窗口

     

     

     事件处理函数需要完全按照它本身虚函数定义,在子类中重新写一遍 (返回值 函数名 传入参数类型都需要完全一致)

    mylabel.h

    1. #ifndef MYLABEL_H
    2. #define MYLABEL_H
    3. #include
    4. class Mylabel : public QLabel
    5. {
    6. Q_OBJECT
    7. public:
    8. explicit Mylabel(QWidget *parent = nullptr);
    9. signals:
    10. // 事件处理函数
    11. protected:
    12. void mousePressEvent(QMouseEvent *ev);
    13. void mouseReleaseEvent(QMouseEvent *ev);
    14. void mouseMoveEvent(QMouseEvent *ev);
    15. public slots:
    16. };
    17. #endif // MYLABEL_H

    mylabel.cpp

    1. #include "mylabel.h"
    2. #include
    3. #include
    4. Mylabel::Mylabel(QWidget *parent) : QLabel(parent)
    5. {
    6. // 设置追踪鼠标
    7. this->setMouseTracking(true);
    8. }
    9. void Mylabel::mousePressEvent(QMouseEvent *ev)
    10. {
    11. int x = ev->x();
    12. int y = ev->y();
    13. // 格式化组包
    14. // QString = str = QString("abc %1 ^_^ %2").arg(123).arg("heqiunong");
    15. // str = abc 123 ^_^ heqiunong
    16. QString str = QString("

      Mouse Press: (%1, %2)

      "
      ).arg(x).arg(y);
    17. this->setText(str);
    18. // 鼠标左键按下
    19. if(ev->button() == Qt::LeftButton)
    20. {
    21. qDebug() << "鼠标左键按下";
    22. }
    23. // 鼠标右键按下
    24. else if(ev->button() == Qt::RightButton)
    25. {
    26. qDebug() << "鼠标右键按下";
    27. }
    28. // 鼠标中键按下
    29. else if(ev->button() == Qt::MidButton)
    30. {
    31. qDebug() << "鼠标中键按下";
    32. }
    33. }
    34. void Mylabel::mouseReleaseEvent(QMouseEvent *ev)
    35. {
    36. QString str = QString("

      Mouse Release: (%1, %2)

      "
      ).arg(ev->x()).arg(ev->y());
    37. this->setText(str);
    38. }
    39. void Mylabel::mouseMoveEvent(QMouseEvent *ev)
    40. {
    41. QString str = QString("

      Mouse Move: (%1, %2)

      "
      ).arg(ev->x()).arg(ev->y());
    42. this->setText(str);
    43. }

     运行结果

     

     

    3、主要窗口对象-键盘事件和定时器事件(注意:它也是QWidget的子类喔)

    widget.h

    1. #ifndef WIDGET_H
    2. #define WIDGET_H
    3. #include
    4. QT_BEGIN_NAMESPACE
    5. namespace Ui { class Widget; }
    6. QT_END_NAMESPACE
    7. class Widget : public QWidget
    8. {
    9. Q_OBJECT
    10. public:
    11. Widget(QWidget *parent = nullptr);
    12. ~Widget();
    13. protected:
    14. // 键盘按下事件
    15. void keyPressEvent(QKeyEvent *event);
    16. // 定时器事件
    17. void timerEvent(QTimerEvent *e);
    18. private:
    19. Ui::Widget *ui;
    20. int timer1Id; // 定时器ID
    21. int timer2Id; // 定时器ID
    22. };
    23. #endif // WIDGET_H

     widget.cpp

    1. #include "widget.h"
    2. #include "ui_widget.h"
    3. #include
    4. #include
    5. Widget::Widget(QWidget *parent)
    6. : QWidget(parent)
    7. , ui(new Ui::Widget)
    8. {
    9. ui->setupUi(this);
    10. timer1Id = this->startTimer(1000); // 单位是ms, 1000表示1s产生一次中断
    11. timer2Id = this->startTimer(100);
    12. }
    13. Widget::~Widget()
    14. {
    15. delete ui;
    16. }
    17. // 键盘按下事件
    18. void Widget::keyPressEvent(QKeyEvent *event)
    19. {
    20. qDebug() << event->key();
    21. if(event->key() == Qt::Key_A){
    22. qDebug() << "Qt::Key_A";
    23. }
    24. }
    25. // 定时器事件
    26. void Widget::timerEvent(QTimerEvent *e){
    27. // 判断是那个定时器
    28. if(e->timerId()==this->timer1Id){
    29. static int sec = 0;
    30. sec++;
    31. QString str = QString("

      timer1: %1

      "
      ).arg(sec);
    32. ui->label_2->setText(str);
    33. if(sec >= 10){
    34. this->killTimer(timer1Id); // 关闭定时器
    35. QString str = QString("

      timer1 is killed

      "
      );
    36. ui->label_2->setText(str);
    37. }
    38. }else if(e->timerId()==this->timer2Id){
    39. static int sec1 = 0;
    40. sec1++;
    41. QString str = QString("

      timer 2: %1

      "
      ).arg(sec1);
    42. ui->label_3->setText(str);
    43. }
    44. }

    运行结果:

     

    4、事件的使用总结

    虽然学qt事件的时候还有其它的内容,比如:事件的接收和忽略、event()、事件过滤器。看看下面这个图了解一些就可以了。

    事件的使用方法主要就是上面提到的,自己在子类里面去写特定的事件处理函数。

     那么我怎么知道我这个控件,有哪些事件呢?

    比如QLabel

     

    比如QWidget

     事件函数,有两个特点, ① 前面是virtual, ②函数名称中带有 Event。

    5、Qt提示补全

    我们在代码的时候, 很多时候需要依靠Qt的补全提示功能。比如你在子控件里面重新定义事件处理函数的时候。

    但有时候Qt的补全提示功能是失效的,有时候它不提示。

    这时候,(难搞,我现在还没搞明白,代码写的不够,后面有体会了再来补充吧)

    1、我们可以通过F1找到这个事件处理函数的定义,然后抄过来。

    2、或者是,在头文件添加相应的定义。

    3、在前面加一下父类的名字

           比如 先把void QWidget::写出来,就能弄出来

           光写 QWidget::后面的参数带不出来。

    4、Ctrl+空格是Qt自动补全的快捷键,容易和输入法切换快捷键冲突

    工具->选项->环境->CompleteThis

    感谢您的阅读,欢迎留言讨论、收藏、点赞、分享。 

  • 相关阅读:
    springboot生成图片并在图片上添加字体进行换行
    计算几何基础知识
    ST-Link的LED指示灯说明
    Greenplum数据库故障分析——能对数据库base文件夹进行软连接嘛?
    广和通5G AIoT模组引领亮相2022国际物联网展(IOTE),智赋行业数字化新价值
    Python3 列表,元组,字典 在数据结构方面的使用
    webpack:css代码提取插件extract-text-webpack-plugin和mini-css-extract-plugin
    C Primer Plus(6) 中文版 第2章 C语言概述 2.3 简单程序的结构
    【云原生Kubernetes系列第五篇】kubeadm v1.20 部署K8S 集群架构(人生这道选择题,总会有遗憾)
    Android 设计模式--状态模式
  • 原文地址:https://blog.csdn.net/heqiunong/article/details/127668970