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

网站平台开发与应用面试网站推广宣传

网站平台开发与应用面试,网站推广宣传,昆明网站建设方案策划,wordpress镜像是什么Qt事件 除了信号和槽通信机制外#xff0c;Qt中还提供了事件处理机制实现与用户的交互和对象间的通信。Qt捕获底层操作系统消息#xff0c;进行封装之后转换为Qt事件#xff0c;事件处理后才发出信号。 一、事件概述Qt中事件是程序内部或外部发生的动作。比如程序外部#…Qt事件 除了信号和槽通信机制外Qt中还提供了事件处理机制实现与用户的交互和对象间的通信。Qt捕获底层操作系统消息进行封装之后转换为Qt事件事件处理后才发出信号。 一、事件概述Qt中事件是程序内部或外部发生的动作。比如程序外部用户移动鼠标、单击鼠标、鼠标拖拽、按下按键等操作都会产生对应的事件。程序内部窗口第一次显示、放大、缩小等。两类事件外部事件用户操作导致的 就是人跟程序互动时触发的比如 你 移动鼠标 → 程序收到一个“鼠标移动事件”。你 单击鼠标 → 程序收到一个“鼠标点击事件”。你 按下键盘 → 程序收到一个“键盘按下事件”。你 拖动窗口 → 程序收到“鼠标拖拽事件”。就好比你在敲门、按电梯按钮程序必须做出反应。内部事件程序自己触发的 就算你啥都不点程序自己也会产生一些动作比如 窗口 第一次显示 → 产生“窗口显示事件”。窗口被 放大/缩小 → 产生“窗口大小改变事件”。程序定时器到点了 → 产生“定时器事件”。就像手机自己亮屏、锁屏这是系统自己触发的。1、事件来源 事件有两个来源程序外部和程序内部 在与用户交互时产生比如用户点击鼠标、按下按键等此时操作系统会感知到用户的行为并产生消息然后将消息投递到应用程序的消息队列当中应用程序从消息队列中提取消息并将其转化为Qt事件生产事件对象。由Qt应用程序自身产生。例如当窗口第一次显示时会产生一个绘制事件以通知窗口需要重新绘制自身从而使窗口可见。这是由程序内部产生的事件。 2、Qt事件处理机制 1当操作系统发生一个事件时事件首先会被操作系统内核中的设备驱动程序所感知然后发送给操作系统的事件管理系统事件管理系统将其放入到事件队列中。 2Qt应用程序作为一个客户端通过调用QApplication的exec()函数启动事件循环这个循环会不断地从事件队列取出事件Qt捕获之后会将该事件转换为相应的Qt事件对象。 3事件自己不能处理自己循环中依次取出事件首先交给notify()函数通过notify()函数派发给处理事件的对象。由QObject类以及其派生类对象进行事件的处理通过重写event()函数或重写对应的事件处理函数完成事件的处理。完整流程总结 程序运行后QApplication::exec() 启动事件循环持续监听事件事件产生后先到 QApplication::notify() 做全局处理再传递到目标 QObject 的 event() 方法识别事件类型最终调用具体的 xxxEvent() 函数执行实际逻辑。 3、事件与信号 Qt的事件与信号很容易混淆。 事件是底层操作系统所产生的消息由Qt捕获之后封装为对应的事件对象比如鼠标单击对应的事件类型是 QEvent::MouseButtonPress.我们在程序中可以通过重写对应的事件处理函数或event()函数进行事件的处理。 Qt为了方便事件的处理引入了信号Signal的概念封装了一些事件操作的标准预处理比如对QPushButton预定义了clicked()信号。使用户不必去处理底层事件只需要处理信号即可。当一个事件触发后对象通过发射一个信号Signal进行通知而其他对象的槽函数Slot可以连接到这个信号从而实现对事件的处理。 信号是对事件的封装。 二、事件类型 常见的事件类型包括 键盘事件如QKeyEvent当用户按下或释放键盘按键时产生鼠标事件如QMouseEvent包含鼠标点击、移动、滚轮滚动等操作窗口事件如resize、paint、move等与窗口大小、位置、重绘相关的事件 Qt捕获之后会将该事件转换为相应的Qt事件对象所有事件都是QEvent类或其派生类的实例常见的事件类如下类名作用QMouseEvent鼠标事件QWheelEvent滚轮事件QKeyEvent键盘事件QPaintEvent绘画事件QTimerEvent定时器事件QResizeEvent窗口大小改变事件QCloseEvent关闭事件QShowEvent显示事件QHideEvent隐藏事件三、鼠标事件 用户点击鼠标 → 硬件信号 → 操作系统事件 → Qt 事件循环接收 → 转换为 QMouseEvent → 传递给按钮 → 按钮判断有效后发出 clicked() 信号 → 连接的槽函数执行鼠标事件涉及鼠标左键或右键按下释放、双击、移动等操作。QMouseEvent类用于处理鼠标事件。事件处理函数都是虚函数全部声明在QWidget类中如果要在子类中处理事件需要重写对应的事件处理函数。 与鼠标事件相关的处理函数如下事件处理函数参数类型描述mousePressEvent()QMouseEvent鼠标按键按下mouseDoubleClickEvent()QMouseEvent鼠标双击mouseReleaseEvent()QMouseEvent鼠标释放mouseMoveEvent()QMouseEvent鼠标移动wheelEvent()QWheelEvent鼠标滚轮滚动1、重写鼠标事件函数 创建QWidget类的子类重写事件处理函数 widget.h #ifndef WIDGET_H #define WIDGET_H#include QWidget // QWidget 是所有界面部件的基类 #include QPoint // QPoint 用于存储点的坐标namespace Ui { class Widget; // 前向声明 Qt Designer 生成的 Ui::Widget 类 }class Widget : public QWidget {Q_OBJECT // Qt 的宏启用信号与槽机制public:explicit Widget(QWidget *parent nullptr); // 构造函数~Widget(); // 析构函数protected:// 重写鼠标按下事件函数用于获取鼠标点击位置void mousePressEvent(QMouseEvent *e) override;// 重写鼠标滚轮事件函数用于实现图标放大/缩小void wheelEvent(QWheelEvent *e) override;// 重写鼠标移动事件函数用于实现窗口拖动void mouseMoveEvent(QMouseEvent *event) override;private:Ui::Widget *ui; // UI 界面指针QPoint offset; // 鼠标相对于窗口左上角的偏移量用于拖动窗口 };#endif // WIDGET_H widget.cpp #include widget.h #include ui_widget.h #include QMouseEvent // 鼠标事件类 #include QDebug // 调试输出// 构造函数 Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui-setupUi(this); // 初始化 UIui-label-setPixmap(QPixmap(:/images/iot.png)); // 在 label 上显示图片ui-label-setScaledContents(true); // 图片随 label 大小自动缩放setWindowFlags(Qt::FramelessWindowHint | windowFlags()); // 去掉窗口边框自绘窗口 }// 析构函数 Widget::~Widget() {delete ui; // 释放 UI 内存 }// 鼠标按下事件 void Widget::mousePressEvent(QMouseEvent *event) {if (event-type() QEvent::MouseButtonPress) // 判断是否是鼠标按下事件{if (event-button() Qt::LeftButton) // 如果是鼠标左键{qDebug() 鼠标左键被按下位于用户区坐标 event-pos() 屏幕坐标 event-globalPos();offset event-pos(); // 记录鼠标按下时鼠标相对于窗口的位置用于拖动窗口}else // 如果是鼠标右键{qDebug() 鼠标右键被按下位于用户区坐标 event-pos();}} }// 鼠标滚轮事件 void Widget::wheelEvent(QWheelEvent *e) {// angleDelta().y() 0 表示向上滚动 0 表示向下滚动if (e-angleDelta().y() 0) // 滚轮向上放大图片{ui-label-resize(ui-label-width()5, ui-label-height()5);}else // 滚轮向下缩小图片{ui-label-resize(ui-label-width()-5, ui-label-height()-5);} }// 鼠标移动事件 void Widget::mouseMoveEvent(QMouseEvent *event) {if (event-buttons() Qt::LeftButton) // 当鼠标左键按下并移动时{// 移动窗口位置// globalPos() 是鼠标在屏幕上的坐标// offset 是鼠标相对窗口的偏移量// 两者相减得到窗口新的左上角位置this-move(event-globalPos() - offset);} } mousePressEvent(QMouseEvent *e)处理鼠标按下事件。 左键记录点击位置用于窗口拖动。右键只是输出调试信息。 wheelEvent(QWheelEvent *e)处理鼠标滚轮事件。 向上滚放大图片。向下滚缩小图片。 mouseMoveEvent(QMouseEvent *event)处理鼠标移动事件拖动窗口。 鼠标按住左键拖动时计算窗口新位置并移动窗口。 2、QMouseEvent对象 QMouseEvent封装鼠标事件的类常用的成员函数成员函数描述Qt::MouseButton button() const;返回产生事件的按钮QPoint globalPos() const;返回鼠标的位置使用屏幕坐标QPoint pos() const;返回鼠标的位置使用用户区坐标QEvent::Type type() const返回事件类别如按下、释放或双击等3、QWheelEvent对象 QWheelEvent类封装了鼠标滚轮事件如滚轮滚动的方向、幅度、位置等。 常用的成员函数成员函数描述QPoint pos() const;返回事件发生时鼠标的位置用户区坐标QPoint globalPos() const;返回事件发生时鼠标的位置屏幕坐标QPoint angleDelta() const;返回滚轮的滚动量在 Qt 里事件函数event handler 是 QWidget 或其他控件类自带的虚函数比如 mousePressEvent(QMouseEvent *e) —— 鼠标按下wheelEvent(QWheelEvent *e) —— 鼠标滚轮keyPressEvent(QKeyEvent *e) —— 键盘按下paintEvent(QPaintEvent *e) —— 绘制事件为什么要 重写override 这些函数 Qt 已经帮我们定义了这些事件函数但默认实现是“什么都不做” 比如 mousePressEvent() 默认不会帮你输出坐标也不会帮你移动窗口。如果你需要自定义行为就要 重写 它们写上自己的逻辑。 让控件有“特殊功能” 例子重写 mousePressEvent实现点击后窗口能拖动。如果不重写窗口只能被系统默认拖动有标题栏时去掉边框后根本没法拖动。 事件驱动编程的核心 Qt 是 事件驱动 的鼠标、键盘、窗口变化都会产生事件。程序如何响应这些事件就要靠重写事件函数。举个通俗例子 把 事件函数 想象成「门铃」。 Qt 框架默认帮你装好一个门铃函数。系统按门铃鼠标点击 / 滚轮滚动 / 按键就会触发事件。如果你没写不重写按门铃没人理默认什么都不做。如果你写了重写就能定义 门铃响时开灯门铃响时开门门铃响时发个消息✅ 所以 重写事件函数 告诉程序当某个事件发生时你要如何反应。 四、键盘事件 1、键盘事件处理函数事件处理函数对应事件类型参数类型描述void keyPressEvent(QKeyEvent *event);QEvent::KeyPressQKeyEvent按键按下void keyReleaseEvent(QKeyEvent *event);QEvent::KeyReleaseQKeyEvent按键释放下面是处理键盘事件的示例 通过按键移动图片重写键盘按下事件的处理函数。 #ifndef KEYEVENTWIDGET_H // 头文件防卫防止重复包含 #define KEYEVENTWIDGET_H#include QWidget // QWidget 是所有可视化窗口控件的基类namespace Ui { class KeyEventWidget; // 声明一个 UI 命名空间里的 KeyEventWidget 类Qt Designer 生成 }class KeyEventWidget : public QWidget // 自定义类继承 QWidget {Q_OBJECT // Qt 元对象系统宏支持信号槽机制等public:explicit KeyEventWidget(QWidget *parent nullptr); // 构造函数支持父子对象机制~KeyEvevtWidget(); // 析构函数释放资源这里注意拼写错了应该是 KeyEventWidgetprotected:// 处理按键事件void keyPressEvent(QKeyEvent *e); // 重写 QWidget 的键盘按下事件函数private:Ui::KeyEventWidget *ui; // 指向 UI 界面类的指针Qt Designer 自动生成的 UI 操作接口 };#endif // KEYEVENTWIDGET_H // 文件结尾的防卫符号 继承 QWidget KeyEventWidget 是一个自定义窗口类继承自 QWidget可以显示在界面上。 重写 keyPressEvent(QKeyEvent *e) 这是 Qt 里专门处理键盘按下的事件函数。默认实现是“不处理”所以我们重写后可以实现 按下某个键时打印信息按下 Esc 键关闭窗口按下方向键移动控件KeyEvevtWidget.cpp #include KeyEventWidget.h // 包含自定义的 KeyEventWidget 类头文件 #include ui_keyeventwidget.h // 包含 Qt Designer 生成的 UI 类定义 #include QWheelEvent // 包含鼠标滚轮事件类虽然这里没用到 #include QKeyEvent // 包含键盘事件类KeyEventWidget::KeyEventWidget(QWidget *parent): QWidget(parent) // 调用 QWidget 构造函数初始化父类, ui(new Ui::KeyEventWidget) // 创建 UI 类的对象 {ui-setupUi(this); // 设置 UI 界面关联 .ui 文件中的控件ui-label-setStyleSheet(background-color: #ccc; height: 200px; width:100px); // 设置 label 的样式灰色背景固定大小200 高100 宽 }KeyEventWidget::~KeyEventWidget() // 析构函数 {delete ui; // 删除 UI 对象释放内存 }void KeyEventWidget::keyPressEvent(QKeyEvent *e) // 重写按键事件处理函数 {// 按上方向键 → 标签向上移动 5 像素if (e-key() Qt::Key_Up){ui-label-move(ui-label-x(), ui-label-y()-5);}// 按下方向键 → 标签向下移动 5 像素else if (e-key() Qt::Key_Down){ui-label-move(ui-label-x(), ui-label-y()5);}// 按左方向键 → 标签向左移动 5 像素else if (e-key() Qt::Key_Left){ui-label-move(ui-label-x()-5, ui-label-y());}// 按右方向键 → 标签向右移动 5 像素else if (e-key() Qt::Key_Right){ui-label-move(ui-label-x()5, ui-label-y());}// 按下 Ctrl M 组合键else if (e-key() Qt::Key_M e-modifiers() Qt::ControlModifier){// 如果窗口是最大化的 → 还原窗口if (windowState() Qt::WindowMaximized) {setWindowState(windowState() ~Qt::WindowMaximized);} // 否则 → 最大化窗口else {setWindowState(Qt::WindowMaximized);}}// 其他按键 → 使用父类默认处理else{QWidget::keyPressEvent(e);} }e-key() Qt::Key_M 判断用户按下的是否是 M 键。e-modifiers() Qt::ControlModifier 判断是否同时按住了 Ctrl 键。 modifiers() 表示组合键比如 Ctrl、Shift、Alt。这里检查是否等于 Qt::ControlModifier也就是 Ctrl 键。所以整体条件按下 CtrlM。windowState() 返回窗口的当前状态比如 Qt::WindowNoState → 普通状态Qt::WindowMaximized → 最大化Qt::WindowMinimized → 最小化Qt::WindowFullScreen → 全屏if (windowState() Qt::WindowMaximized)是按位与运算检查当前窗口状态里是否包含 最大化。如果是最大化 → 进入还原操作。setWindowState(windowState() ~Qt::WindowMaximized); ~Qt::WindowMaximized 表示“去掉最大化这个标志”。windowState() ~Qt::WindowMaximized → 当前状态里去掉“最大化”。也就是说把窗口从最大化还原回普通大小。else { setWindowState(Qt::WindowMaximized); } 如果当前不是最大化 → 就设置成最大化。Qt 里的 windowState() 返回的值其实就像 MCU单片机里寄存器的值 每一位或者说每个二进制标志位代表一个“开关”状态。如果该位是 1说明这个状态 启用如果该位是 0说明这个状态 未启用。例如 Qt 定义的窗口状态简化状态宏二进制位说明Qt::WindowNoState0000默认普通状态Qt::WindowMinimized0001最小化Qt::WindowMaximized0010最大化Qt::WindowFullScreen0100全屏 如果 windowState() 返回 0010 → 表示窗口是 最大化0001 → 表示窗口是 最小化0011 → 表示窗口同时有 最小化 最大化可能组合状态 那么 if (windowState() Qt::WindowMaximized)就是在问“这个二进制值的 第2位最大化标志是不是 1” 如果是 1就说明当前窗口已经最大化。所以它和寄存器检查位完全一样。 在嵌入式里我们常写 if (reg (13)) { ... } // 检查寄存器的第3位在 Qt 里就是 if (windowState() Qt::WindowMaximized) { ... }2、QKeyEvent对象 用于描述键盘事件常用成员函数成员函数描述int key() const;获取按下的键int modifiers() const;判断修饰键Ctrl、Shift、Alt是否在按下状态五、重写event()事件函数 event()函数是QObject类所提供的特定事件处理函数仅能处理预定义的事件类型而event()函数可以处理所有类型的事件。 对于只需要处理某种特定类型事件的情况重写对应的特定事件处理函数会更加直接。如果需要对多种不同类型的事件进行处理那么就重写event()函数。 下面是重写event()实现事件处理示例 新建MyWidget类mywidget.h文件如下 #ifndef MYWIDGET_H // 头文件保护防止重复包含 #define MYWIDGET_H#include QWidget // 引入 QWidget 基类MyWidget 要继承它namespace Ui { class MyWidget; // 前向声明 UI 界面类Qt Designer 生成的类 }class MyWidget : public QWidget // 定义 MyWidget 类继承自 QWidget {Q_OBJECT // Qt 的元对象宏支持信号槽、事件机制等public:explicit MyWidget(QWidget *parent nullptr); // 构造函数父对象默认为空~MyWidget(); // 析构函数释放资源// 重写 Qt 的事件处理函数 event()// 所有事件鼠标、键盘、窗口等都会先经过 event()// 返回 true 表示事件已处理不需要再传递false 表示未处理交给默认处理bool event(QEvent *event);protected:// 自定义的鼠标事件处理函数自己写的名字不是 Qt 内置的void doPressEvent(QMouseEvent *event);private:Ui::MyWidget *ui; // UI 界面指针指向 Qt Designer 生成的界面类 };#endif // MYWIDGET_H // 头文件保护宏结束event(QEvent *event) Qt 的 事件分发函数。凡是传给这个窗口的事件鼠标、键盘、窗口大小变化等都会先经过它。如果你重写它可以统一拦截和处理不同类型的事件。 doPressEvent(QMouseEvent *event) 这是你 自定义的函数不是 Qt 框架强制要求的。一般用来在 event() 里检测到鼠标事件后专门调用它来处理。相当于你自己封装的“鼠标事件处理逻辑”。 返回值 bool 的意义 true → 表示事件在这里已经被处理完毕Qt 不会再把它传递下去。false → 表示你没处理Qt 会交给默认的父类逻辑继续处理。所以可以理解为 event() → 总入口像一个“事件分发器”。doPressEvent() → 你自己写的业务逻辑处理函数。 mywidget.cpp #include mywidget.h #include ui_mywidget.h #include QEvent #include QMouseEvent #include QDebugMyWidget::MyWidget(QWidget *parent): QWidget(parent) // 调用父类 QWidget 的构造函数, ui(new Ui::MyWidget) // 创建 UI 界面对象 {ui-setupUi(this); // 初始化 UI 布局和控件 }MyWidget::~MyWidget() {delete ui; // 释放 UI 对象防止内存泄漏 }// 重写 QWidget 的事件处理函数 event() bool MyWidget::event(QEvent *event) {if (event-type() QEvent::MouseButtonPress) // 判断是否为鼠标按下事件{// 将接收到的 QEvent 对象强制转换为 QMouseEvent 对象QMouseEvent *mEvent dynamic_castQMouseEvent*(event);// 调用自定义处理函数处理鼠标按下事件doPressEvent(mEvent);// 返回 true 表示事件已被处理不再传递给其他处理函数return true;}// 对于其他类型事件调用基类的 event() 函数进行默认处理return QWidget::event(event); }// 自定义函数用于处理鼠标按下事件 void MyWidget::doPressEvent(QMouseEvent *event) {if (event-button() Qt::LeftButton) // 判断是否为鼠标左键{qDebug() 左键点击; // 打印调试信息}else // 其他情况如右键{qDebug() 右键点击; // 打印调试信息} }事件过滤与处理通过重写 event() 函数可以拦截所有事件类型并根据类型选择性处理。类型转换使用 dynamic_cast 将基类 QEvent* 转换为具体事件类型 QMouseEvent*便于访问特有属性。事件消费返回 true 表示事件已经处理不会继续向父类或其他对象传递。自定义函数解耦将具体的鼠标按下处理逻辑放到 doPressEvent() 函数中使代码结构更清晰。当 Qt 收到一个事件比如鼠标、键盘、绘图请求它会先调用 QWidget::event()。event() 内部会判断事件类型然后再调用更具体的事件处理函数 mousePressEvent()keyPressEvent()paintEvent()…所以 如果你重写了 event()但没有调用 QWidget::event(event)相当于“截断”了事件分发。 ⚠️ 重点Qt 内部的设计就是 依赖 QWidget::event() 去调用其他事件函数。 如果你直接返回 false那些具体的事件函数根本不会被调用。 return QWidget::event(event); 是显式调用 父类版本的 event()让它继续帮你分发事件。 六、定时器事件 Qt的定时器事件主要用于实现周期性或延迟执行任务的功能。对于实时监控、动画效果、定期检查状态变化以及其他需要按时间顺序控制的行为非常有用。 在Qt中有两种主要的方式来使用定时器 1、QTimer类 QTimer是基于事件循环的定时器通过创建一个QTimer对象并调用其start()方法来启动定时器。当设定的时间间隔到期时会自动触发关联的槽函数slot或者发送一个timeout()信号。使用QTimer可以轻松实现在特定时间间隔后执行重复的任务例如更新用户界面、轮询硬件状态、刷新数据等。 2、定时器事件 1对于任意QObject子类可以调用以下成员函数开启定时器 int startTimer(int interval, Qt::TimerType timerType Qt::CoarseTimer);该函数会以interval毫秒为周期开启一个定时器产生一个QTimerEvent定时器事件并返回定时器标识。 Qt::TimerType timerType用于指定计时器的类型 Qt::VeryCoarseTimer这是最不精确的计时器类型可能有几秒钟的误差。这种类型的计时器会消耗最少的系统资源。Qt::CoarseTimer这是一种相对不精确的计时器类型可能有几百毫秒的误差。这种类型的计时器比VeryCoarseTimer更精确但仍然消耗较少的系统资源。Qt::PreciseTimer这是最精确的计时器类型误差通常小于1毫秒。这种类型的计时器提供最高的精度但可能会消耗更多的系统资源。 2QObject子类可以通过重写timerEvent()成员函数处理定时器事件 void timerEvent(QTimerEvent *event);3清除定时器直到调用QObject类里的成员函数 void killTimer(int id);下面是一个定时器事件的示例timerwidget.h #ifndef TIMERWIDGET_H #define TIMERWIDGET_H#include QWidgetnamespace Ui { class TimerWidget; }class TimerWidget : public QWidget {Q_OBJECT public:explicit TimerWidget(QWidget *parent nullptr); // 构造函数~TimerWidget(); // 析构函数protected:// 重写QObject提供的定时器事件处理函数void timerEvent(QTimerEvent *e);private slots:void on_start_clicked(); // “开始”按钮点击槽void on_stop_clicked(); // “结束”按钮点击槽private:Ui::TimerWidget *ui; // UI指针int timerId; // 保存定时器ID用于开启/关闭定时器 };#endif // TIMERWIDGET_H重写定时器事件函数timerwidget.cpp代码如下 #include timerwidget.h #include ui_timerwidget.h #include QTime // 用于显示当前时间TimerWidget::TimerWidget(QWidget *parent): QWidget(parent), ui(new Ui::TimerWidget), timerId(-1) // -1表示当前没有定时器 {ui-setupUi(this); // 创建定时器周期1秒1000msif (timerId -1)timerId startTimer(1000); // startTimer 返回一个 timerId用于killTimer// 美化显示标签ui-label-setStyleSheet(font-size:20px;background-color:#fff;border:1px solid black;border-radius:5px;);ui-label-resize(200, 30); // 设置标签大小 }// 析构函数 TimerWidget::~TimerWidget() {delete ui; // 释放UI对象 }// 定时器事件每当定时器时间到达时这个函数会被自动调用 void TimerWidget::timerEvent(QTimerEvent *e) {Q_UNUSED(e); // 不使用参数// 更新标签显示当前系统时间ui-label-setText(QTime::currentTime().toString()); }// “开始”按钮点击槽函数 void TimerWidget::on_start_clicked() {if (timerId -1) // 如果当前没有定时器则启动timerId startTimer(1000); // 周期1秒 }// “结束”按钮点击槽函数 void TimerWidget::on_stop_clicked() {if (timerId ! -1) // 如果定时器存在{killTimer(timerId); // 停止定时器timerId -1; // 重置ID} }定时器是什么 定时器就像手机闹钟每隔固定时间就“响一次”Qt会给你一个事件让你在 timerEvent() 里处理。定时器ID startTimer() 会返回一个整数ID用来区分不同的定时器。要关闭定时器必须用 killTimer(id)。事件触发 每当时间到Qt会自动调用你重写的 timerEvent(QTimerEvent *e) 函数你在里面写想做的事情比如刷新UI。开始/结束按钮 on_start_clicked()手动开启定时器on_stop_clicked()手动关闭定时器QTimer vs 定时器事件 QTimer 是信号槽方式更现代更方便startTimer() timerEvent() 是事件驱动方式更底层更灵活timerId -1 的含义 int timerId; // 定时器ID timerId -1; // -1 表示当前没有定时器当 timerId -1 时说明当前没有定时器在运行。当 timerId ! -1 时说明已经有一个定时器存在timerId 保存了这个定时器的ID。 如果不判断直接调用 timerId startTimer(1000);每次点击“开始”按钮或构造函数里执行都会再启动一个新的定时器。结果就是同一秒内可能有多个定时器同时触发导致 timerEvent() 被重复调用UI更新混乱。 所以加判断 if (timerId -1) timerId startTimer(1000);确保同一时间只存在一个定时器避免重复触发。Qt能不能同时存在多个定时器 能Qt允许一个对象启动多个定时器每个定时器都有自己的ID。但是你的设计是只需要一个定时器去刷新时间所以只保留一个方便管理和关闭。如果你想同时运行多个定时器需要每个定时器保存自己的ID在 timerEvent(QTimerEvent *e) 里通过 e-timerId() 区分不同的定时器。 七、事件过滤器Qt中的事件过滤器机制允许在对象接收到事件之前拦截和处理这些事件。使用事件过滤器可以在不直接修改对象代码的情况下增加额外的事件处理逻辑。事件过滤器的用途 监视和响应特定对象的事件而无需直接修改对象的代码拦截事件在事件达到目标对象之前进行预处理或完全阻止事件实现跨多个对象的通用事件处理逻辑而不需要在每个对象所属的类中定义重复相同的代码 事件过滤器的使用步骤 安装事件过滤器给要进行事件过滤的对象组件安装事件过滤器开发事件过滤器对事件进行拦截处理。进行事件拦截处理的对象需要重写QObject::eventFilter()函数进行事件的处理事件处理如果eventFilter()返回true表示事件处理完毕如果返回false事件将继续传递最终到达目标对象。 1、安装事件过滤器 使用QObject::installEventFilter()函数将一个事件过滤器对象安装到需要进行事件过滤的对象上。 obj-installEventFilter(this);在UI可视化界面拖放一个QLabel组件为该组件安装事件过滤器 // 为标签label控件安装事件过滤器事件过滤器会监视所有传递给该 label 的事件。 //这里this是指向实现了事件过滤逻辑的对象。将事件的处理交给该对象。 ui-label-installEventFilter(this);2、重写eventFilter()函数 对事件进行过滤器处理的对象必须重写QObject::eventFilter()虚函数。 它的主要作用是在事件传递给目标对象之前提供一个拦截点。在事件到达目标对象之前对其进行处理、修改甚至阻止。 watched: 参数是一个指向被监视对象的指针。这个对象就是调用installEventFilter函数安装过滤器的那个对象。event: 参数是一个指向事件的指针表示正在传递给watched对象的事件virtual bool eventFilter(QObject *watched, QEvent *event);watched类型QObject*含义正在被你监视的对象就是你之前调用 installEventFilter(this) 的那个控件。例子 ui-textEdit-installEventFilter(this);那么 watched 就可能是 ui-textEdit。作用通过它你可以知道“这个事件是哪个控件发来的”这样你可以针对不同控件做不同处理。event类型QEvent*含义正在发生的事件本身事件的类型很多比如 QEvent::KeyPress → 按键事件QEvent::MouseButtonPress → 鼠标点击事件QEvent::FocusIn → 焦点进入事件作用你可以通过它获取事件的详细信息例如 if(event-type() QEvent::KeyPress){QKeyEvent* keyEvent dynamic_castQKeyEvent*(event);if(keyEvent-key() Qt::Key_Return){// 按下的是回车} }watched → 谁发的事件 event → 事件是什么 3、案例在一个窗口中有一个多行文本输入框QTextEdit需要让我们屏蔽掉键盘上的回车键也就是按回车键之后在这个文本编辑框中再也不能换行了。其实上面的需求有三种解决方案 自定义一个新的类让其继承QTextEdit在这个子类中重写键盘事件keyPressEvent在这个函数里边屏蔽掉回车键自定义一个新的类让其继承QTextEdit在这个子类中重写事件分发器event在这个函数里边屏蔽掉回车键给QTextEdit安装事件过滤器基于QTextEdit的父窗口对这个控件的事件进行过滤 最简单的方式还是第三种因为我们不需要再定义出一个子类就可以轻松的完成控件事件的过滤了。 准备工作在主窗口中添加一个QTextEdit类型的控件如下图主窗口头文件 widget_01.h class widget_01 : public QWidget {Q_OBJECTpublic:explicit widget_01(QWidget *parent nullptr); // 构造函数~widget_01(); // 析构函数// 重写事件过滤器函数bool eventFilter(QObject *watched, QEvent *event) override;private:Ui::widget_01 *ui; // UI指针 }; 主窗口源文件 widget_01.cpp widget_01::widget_01(QWidget *parent) :QWidget(parent),ui(new Ui::widget_01) {ui-setupUi(this); // 初始化UI界面// 安装事件过滤器把textEdit的事件交给当前对象处理ui-textEdit-installEventFilter(this); // 安装过滤器后所有textEdit事件会先到eventFilter }widget_01::~widget_01() {delete ui; // 释放UI对象 }// 事件过滤器函数 bool widget_01::eventFilter(QObject *watched, QEvent *event) {// 判断事件来源是否是 textEdit并且事件类型是否为按键事件if(watched ui-textEdit event-type() QEvent::KeyPress){// 将 QEvent 转换为 QKeyEvent 以获取按键信息QKeyEvent *pKeyEvent dynamic_castQKeyEvent*(event);// 判断按键是否为回车键if(pKeyEvent-key() Qt::Key_Return){qDebug() 回车...; // 打印调试信息return true; // 返回true表示事件已被处理不再向下传递}} // 对于其他事件调用基类的eventFilter处理return QWidget::eventFilter(watched, event); }事件过滤器作用 可以拦截指定对象的事件如 textEdit 的按键、鼠标等事件在到达对象本身之前先处理。常用于想对某个控件做特殊行为但不想修改控件内部逻辑的场景。 installEventFilter(this) 安装过滤器后控件的事件会先到过滤器对象的 eventFilter()。可以选择处理返回 true或传递返回 false 或调用基类。 事件类型判断 event-type() 用于判断事件类型比如 QEvent::KeyPress、QEvent::MouseButtonPress 等。 事件消费 返回 true事件被拦截不再传递给控件自身。返回 false 或调用基类事件继续传递控件可自行处理。 类型转换 使用 dynamic_castQKeyEvent* 将 QEvent* 转换为 QKeyEvent*可以访问按键信息如 key()。
http://www.pierceye.com/news/452758/

相关文章:

  • 工业园区门户网站建设方案塘沽网站开发
  • 郑州网站设计 公司驻马店市可以做网站的公司
  • 推荐盐城网站开发安陆网站开发
  • wordpress中文网站模板软件开发者路线图
  • 福清市建设局网站深圳网站制作品牌祥奔科技
  • 工程建设采购有哪些网站做网络销售怎么样
  • wordpress数据库和网站文件下载商业网站成功的原因
  • 30岁转行做网站设计百度秒收网站
  • 网页设计与制作心得体会1000福州网站seo公司
  • 学校网站定位手机网站建设怎么样
  • 苏州科技网站建设模板网站 seo
  • 免费qq刷赞网站推广网站建设具体项目及价格
  • 怎么做网站页面代码搜索网站的根目录
  • 网站建设免责申明书做qq图片的网站吗
  • 营销型单页网站电子商务平台建设
  • 去柬埔寨做网站是传销吗app推广服务部
  • 网站建站的流程海南住建部建设网站的网站
  • 网站建设与推广的步骤网站建设费用如何做账务处理
  • 简单网站建设运营网页改版
  • 赣州网站建设江西网站建设怎么用网页制作一个网站
  • phpcms v9怎么做网站建设项目网站备案
  • 徐州市建设局网站电话号码网站怎么实现两种语言
  • 做网站涉及到哪些浙江城乡建设网站证件查询
  • 重庆市园林建设有限公司网站太原网站建设51sole
  • 淘宝客推广怎么做网站备案全国建设项目竣工验收公示网站
  • 数据型网站 建设方案建材类网站建设方案
  • 怎么和网站主联系方式seo站长工具箱
  • 西安网站运营招聘深圳网站设计公司电话
  • 老外的网站怎么做大学生个人网站制作
  • 顺德网站建设如何推广计划和推广单元