初识——QT

QT安装方法

一、项目创建流程
  1. 创建项目

    • 入口:通过Qt Creator的欢迎页面或菜单栏(文件→新建项目)创建新项目。

    • 项目类型:选择「Qt Widgets Application」。

    • 路径要求:项目路径需为纯英文且不含特殊字符。

    • 构建系统:默认选择 CMake

    • 类配置:默认生成MainWindow类(包含UI文件)。

  2. 配置构建套件

    • 选择适用于当前平台的构建套件(如MinGW/MSVC)。

    • 若CMake配置失败,需检查CMake路径或更新组件。

  3. 运行项目

    • 点击「运行」按钮,生成默认窗口界面(含一个空Widget)。

二、工程文件解析
  1. CMakeLists.txt

    • 核心作用:定义项目构建规则、依赖关系及编译选项。

    • 关键配置

      cmake_minimum_required(VERSION 3.10)  # 指定CMake最低版本
      project(qt01 VERSION 0.1 LANGUAGES CXX)  # 设置项目名称及语言
      set(CMAKE_CXX_STANDARD 17)  # 指定C++标准为C++17
      find_package(Qt6 REQUIRED COMPONENTS Widgets)  # 引入Qt6 Widgets模块
      add_executable(qt01 main.cpp)  # 定义可执行文件
      target_link_libraries(qt01 PRIVATE Qt6::Widgets)  # 链接Qt库
    • 注意事项:需通过find_package引入所需Qt模块(如Widgets、Core等)。

  2. mainwindow.h

    • 功能:声明主窗口类,继承自QMainWindow

    • 关键代码

      #include <QMainWindow>
      namespace Ui { class MainWindow; }  // 前向声明UI类
      class MainWindow : public QMainWindow {Q_OBJECT  // 必须包含Q_OBJECT宏以支持信号与槽
      public:MainWindow(QWidget *parent = nullptr);~MainWindow();
      private:Ui::MainWindow *ui;  // UI对象指针
      };
  3. mainwindow.cpp

    • 功能:实现主窗口类的构造函数和析构函数。

    • 关键代码

      #include "mainwindow.h"
      #include "ui_mainwindow.h"
      MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this);  // 初始化UI(自动生成)
      }
      MainWindow::~MainWindow() { delete ui; }  // 释放UI对象
  4. main.cpp

    • 功能:应用程序入口,创建主窗口并启动事件循环。

    • 关键代码

      #include "mainwindow.h"
      #include <QApplication>
      int main(int argc, char *argv[]) {QApplication a(argc, argv);  // 管理GUI程序生命周期MainWindow w;w.show();  // 显示窗口return a.exec();  // 进入事件循环
      }
    • 注意a.exec()是Qt事件循环的核心,负责处理用户输入和窗口事件。

  5. ui_mainwindow.h

    • 功能:由Qt Designer自动生成的UI布局代码,描述窗口中的控件及其属性。

三、Qt内存管理机制
  1. 父子对象关系

    • 规则:父对象销毁时自动删除所有子对象。

    • 示例

      QWidget *parent = new QWidget;
      QPushButton *button = new QPushButton(parent);  // button的父对象为parent
      delete parent;  // 自动删除button
  2. 智能指针

    • QScopedPointer:作用域内自动释放内存。

    • QSharedPointer:引用计数智能指针,共享所有权。

四、UI设计与信号槽
  1. 拖拽控件

    • 通过Qt Designer在.ui文件中拖拽控件(如按钮、标签)并设置属性(如文本、大小)。

    • 示例:设置按钮文本:

      ui->pushButton->setText("点我");
  2. 自动连接槽函数

    • 命名规则on_控件对象名_信号名()

    • 示例:按钮点击槽函数:

      void MainWindow::on_pushButton_clicked() {qDebug() << "按钮被点击";
      }
五、注意事项
  1. 路径规范:避免中文和特殊字符,防止构建失败。

  2. CMake配置:确保正确引入Qt模块(如Widgets、Core)。

  3. 内存管理:优先使用父子对象关系或智能指针,避免内存泄漏。

  4. UI更新:修改.ui文件后需重新构建以生成ui_*.h文件。

信号与槽机制

一、概述
  • 核心作用:Qt的信号与槽机制是用于对象间通信的松耦合方式,替代传统回调函数。当对象状态变化(事件)时发送信号,连接的槽函数自动响应。

  • 特点:支持多对多连接(一个信号可绑定多个槽,多个信号可绑定一个槽),支持跨线程通信,参数类型需兼容。 

二、信号与槽的定义
  1. 信号(Signal)

    • 声明方式:在类中使用 signals 关键字声明,无返回值(void),无需实现。

    • 示例: 

      class MyClass : public QObject {Q_OBJECT
      signals:void mySignal(int value); // 信号声明
      };
  2. 槽(Slot)

    • 声明方式:在类中使用 public/private/protected slots 声明,是普通成员函数,可带参数和返回值。

    • 示例:

      class MyClass : public QObject {Q_OBJECT
      public slots:void mySlot(int data); // 槽声明
      }; 
三、信号的发送与槽的调用
  • 信号发送:通过 emit 关键字触发信号。

    emit mySignal(100); // 发送信号
  • 槽调用规则

    • 槽函数按连接顺序依次执行。

    • 槽可以是私有函数,但通过信号连接仍可调用。 

四、信号与槽的连接方式
  1. 手动连接

    • 使用 QObject::connect 函数,语法:

      connect(sender, &SenderClass::signal, receiver, &ReceiverClass::slot);
    • 示例:

      connect(ui->pushButton, &QPushButton::clicked, this, &MainWindow::handleClick);
  2. 自动连接

    • 通过槽函数命名规则 on_对象名_信号名,需在 setupUi 中调用 QMetaObject::connectSlotsByName

    • 示例:

      void MainWindow::on_pushButton_clicked() { ... } // 自动连接 
五、连接类型与规则
  1. 连接类型Qt::ConnectionType

    类型描述
    AutoConnection默认,根据线程自动选择 Direct(同线程)或 Queued(跨线程)。
    DirectConnection立即执行,槽在发送者线程运行。
    QueuedConnection异步执行,槽在接收者线程事件循环中调用。
    BlockingQueuedConnection同步执行,发送者线程阻塞直到槽完成(需跨线程)。
    UniqueConnection避免重复连接,与上述类型按位或使用。
  2. 参数规则

    • 信号参数数量 ≥ 槽参数数量,且类型兼容。

    • 示例:

      // 合法:信号参数多于槽
      connect(obj1, &ClassA::signal(int, QString), obj2, &ClassB::slot(int));
      // 非法:槽参数多于信号
      connect(obj1, &ClassA::signal(int), obj2, &ClassB::slot(int, QString)); 
六、自定义信号与槽的条件
  1. 类必须直接或间接继承 QObject

  2. 类声明中需包含 Q_OBJECT 宏。

  3. 信号用 signals 声明,槽用 slots 声明。 

七、元对象编译器(moc)
  • 作用:处理 Qt 的扩展语法(如信号与槽),生成元对象代码(moc_*.cpp)。

  • 必要性:包含 Q_OBJECT 的类必须通过 moc 编译,否则信号与槽无法正常工作。 

八、关键示例
// 信号与槽定义
class Worker : public QObject {Q_OBJECT
signals:void progressUpdated(int percent);
public slots:void doWork() { // 工作逻辑emit progressUpdated(50); }
};// 连接
Worker worker;
QObject::connect(&worker, &Worker::progressUpdated, this, [](int percent) {qDebug() << "Progress:" << percent;
}); 

简单示例:

teacher.h:

// teacher.h
#include <QObject>
class Teacher : public QObject {Q_OBJECT
public:explicit Teacher(QObject *parent = nullptr) : QObject(parent) {}signals:void hungry();  // 正确信号声明
};

student.h:

// student.h
#include <QObject>
#include <QDebug>
class Student : public QObject {Q_OBJECT
public:explicit Student(QObject *parent = nullptr) : QObject(parent) {}public slots:void treat();   // 槽函数声明
};

student.cpp:

// student.cpp
#include "student.h"
void Student::treat() {qDebug() << "Student treats teacher";  // 修正输出内容
}

window.h:

// window.h
#include <QWidget>
#include "teacher.h"
#include "student.h"class Window : public QWidget {Q_OBJECT
public:explicit Window(QWidget *parent = nullptr);public slots:void xiake();  // 触发信号的方法private:Teacher *teacher;Student *student;
};

window.cpp: 

// window.cpp
#include "window.h"Window::Window(QWidget *parent) : QWidget(parent) {teacher = new Teacher(this);student = new Student(this);// 正确连接信号与槽(注意信号拼写)connect(teacher, &Teacher::hungry, student, &Student::treat);
}void Window::xiake() {emit teacher->hungry();  // 触发信号
}
九、注意事项
  1. 线程安全:跨线程通信优先使用 QueuedConnection

  2. 命名规范:自动连接槽需严格遵循 on_对象名_信号名 格式。

  3. 内存管理:避免循环引用,确保对象生命周期可控。

Qt事件处理总结与归纳

一、事件简介
  1. 概念

    • 事件是用户或系统产生的交互操作,通过事件循环处理,用于对象间信息交互。

    • Qt将系统消息转换为QEvent对象,所有QObject子类均可处理事件。

  2. 常见事件类型

    • 用户界面事件:鼠标事件(QMouseEvent)、键盘事件(QKeyEvent)、触摸事件(QTouchEvent)。

    • 系统事件:定时器事件(QTimerEvent)、窗口事件(QResizeEvent)、绘图事件(QPaintEvent)。

    • 自定义事件:继承QEvent实现,用于特定需求。

二、事件处理机制
  1. 事件分发流程

    • 事件队列:操作系统消息被转换为QEvent,由QCoreApplication::exec()驱动的主事件循环处理。

    • 事件传递

      1. 事件先传递到焦点控件。

      2. 若未被处理,逐级传递给父控件。

  2. 事件处理函数

    • 子类可重写event()函数或特定事件处理函数(如mousePressEvent())。

    • 示例:自定义按钮重写鼠标事件:

      // 继承QPushButton并重写mousePressEvent
      void CustomPushButton::mousePressEvent(QMouseEvent *e) {qDebug() << "Custom按钮被按下";QPushButton::mousePressEvent(e); // 调用父类实现,确保信号正常触发
      }
  3. 事件过滤器(Event Filter)

    • 作用:拦截目标对象的事件,在事件到达前处理。

    • 步骤

      1. 安装过滤器targetObj->installEventFilter(filterObj)

      2. 重写eventFilter():判断事件类型并处理,返回true拦截事件,false继续传递。

      bool MainWindow::eventFilter(QObject *obj, QEvent *event) {if (obj == ui->pushButton && event->type() == QEvent::MouseButtonPress) {qDebug() << "拦截按钮点击";return true; // 阻止事件传递}return QMainWindow::eventFilter(obj, event); // 默认处理
      }
三、事件与信号的区别
特性事件(QEvent)信号(Signal)
触发方式由系统或用户操作触发由对象主动发出(如按钮点击触发clicked
处理机制通过事件队列分发,可被过滤或拦截直接调用连接的槽函数
灵活性可自定义事件类型和分发逻辑信号与槽通过connect绑定,不可拦截
典型应用底层交互(如鼠标移动、键盘输入)逻辑响应(如按钮点击后的业务逻辑)
四、QEventLoop 的应用
  1. 作用

    • 在局部范围内启动事件循环,用于等待异步操作完成(如定时器、对话框关闭)。

  2. 使用场景

    • 等待定时器

      QEventLoop loop;
      QTimer::singleShot(3000, &loop, &QEventLoop::quit);
      loop.exec(); // 阻塞3秒后继续执行
    • 模态对话框

      QDialog dialog;
      QEventLoop loop;
      connect(&dialog, &QDialog::finished, &loop, &QEventLoop::quit);
      dialog.show();
      loop.exec(); // 等待对话框关闭
五、常见问题与解决
  1. 头文件缺失

    • 错误customepushbutton.h: No such file or directory

    • 解决:在CMake中添加包含目录:

      include_directories(${PROJECT_SOURCE_DIR})
  2. 类型转换错误

    • 错误invalid conversion from 'QWidget' to 'QPushButton'

    • 解决:确保自定义控件继承自正确的基类(如QPushButton)。

  3. 信号未触发

    • 原因:重写事件处理函数时未调用父类实现。

    • 解决:在自定义的mousePressEvent中调用QPushButton::mousePressEvent(e)

六、总结
  • 事件处理核心:理解事件分发流程、重写事件函数、使用过滤器拦截事件。

  • 事件与信号结合:事件处理底层交互,信号驱动业务逻辑,两者互补。

  • 开发注意事项

    • 继承控件时确保调用父类事件函数以维持原有逻辑。

    • 使用QEventLoop避免主线程阻塞,保持界面流畅。

    • 合理使用事件过滤器实现复杂交互逻辑。

 

  • 这是本人的学习笔记不是获利的工具,小作者会一直写下去,希望大家能多多监督我
  • 文章会每攒够两篇进行更新发布(受平台原因,也是希望能让更多的人看见)
  • 感谢各位的阅读希望我的文章会对诸君有所帮助

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/81251.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

7-15 计算圆周率

π​131​352!​3573!​⋯357⋯(2n1)n!​⋯ 输入格式&#xff1a; 输入在一行中给出小于1的阈值。 输出格式&#xff1a; 在一行中输出满足阈值条件的近似圆周率&#xff0c;输出到小数点后6位。 输入样例&#xff1a; 0.01输出样例&#xff1a; 3.132157 我的代码 #i…

【图片识别工具】批量单据识别批量重命名,批量OCR识别图片文字并重命名,批量改名工具的使用步骤和注意事项

一、适用场景 ​​财务与发票管理​​&#xff1a;企业需处理大量电子发票或扫描件&#xff0c;通过OCR识别发票代码、金额等关键信息&#xff0c;自动重命名为发票号_金额.pdf格式&#xff0c;便于归档与税务审计。 ​​物流单据处理​​&#xff1a;物流公司需从运单中提取单…

Modbus TCP转Profinet网关:数字化工厂异构网络融合的核心枢纽

在现代工业生产中&#xff0c;随着智能制造和工业互联网的不断发展&#xff0c;数字化工厂成为了制造业升级的重要方向。数字化工厂的核心在于实现设备、数据和人的互联互通&#xff0c;而这其中&#xff0c;通信协议扮演着至关重要的角色。今天&#xff0c;我们就来探讨开疆智…

win11平台下的docker-desktop中的volume位置问题

因为需要搞个本地的mysql数据库&#xff0c;而且本地安装的程序较多&#xff0c;不想再安mysql了&#xff0c;就想到使用docker来安装。而且因为数据巨大&#xff0c;所以想到直接使用转移data文件夹的方式。 各种查询&#xff0c;而且还使用ai查询&#xff0c;他们都提到&…

【MySQL】项目实践

个人主页&#xff1a;Guiat 归属专栏&#xff1a;MySQL 文章目录 1. 项目实践概述1.1 项目实践的重要性1.2 项目中MySQL的典型应用场景 2. 数据库设计流程2.1 需求分析与规划2.2 设计过程示例2.3 数据库设计工具 3. 电子商务平台实践案例3.1 系统架构3.2 数据库Schema设计3.3 数…

React学习———CSS Modules(样式模块化)

CSS Modules CSS Modules&#xff08;样式模块化&#xff09;是一种用于模块化和局部作用域化CSS样式的技术&#xff0c;让CSS只在当前组件内生效&#xff0c;避免全局样式冲突的技术方案 工作原理 文件命名&#xff1a;通常以.module.css、.module.less、.module.scss等结尾…

agent 智能体应用产品:生图、生视频、代码等

生图片 Lovart&#xff1a;全球首个设计 Agent https://www.lovart.ai/ 生视频 AI 视频 Agent 产品&#xff1a;Medeo https://www.medeo.app/ 代码 vscode copilot、cursor、trae 其他research manus grok等各个大模型产品

青少年ctf平台应急响应-应急响应2

题目&#xff1a; 当前服务器被创建了一个新的用户&#xff0c;请提交新用户的用户名&#xff0c;得到的结果 ssh rootchallenge.qsnctf.com -p 30327 这个命令用于通过 SSH 协议连接到指定的远程服务器。具体解释如下&#xff1a; ssh&#xff1a;这是在 Unix-like 系统中…

码蹄集——圆包含

MT1181 圆包含 输入2个圆的圆心的坐标值&#xff08;x&#xff0c;y&#xff09;和半径&#xff0c;判断断一个圆是否完全包含另一个圆&#xff0c;输出YES或者NO。另&#xff1a;内切不算做完全包含。 格式 输入格式&#xff1a;输入整型&#xff0c;空格分隔。 每行输入一组…

基于EMD-PCA-LSTM的光伏功率预测模型研究

摘要 本文提出了一种结合经验模态分解(EMD)、主成分分析(PCA)和长短期记忆网络(LSTM)的混合预测模型,用于提高光伏功率预测的准确性。该模型首先利用EMD算法将非平稳的光伏功率序列分解为多个本征模态函数(IMF),然后通过PCA对多维气象特征进行降维处理,最后将处理后的特征输…

MYSQL创建索引的原则

创建索引的原则包括&#xff1a; 表中的数据量超过10万以上时考虑创建索引。 选择查询频繁的字段作为索引&#xff0c;如查询条件、排序字段或分组字段。 尽量使用复合索引&#xff0c;覆盖SQL的返回值。 如果字段区分度不高&#xff0c;可以将其放在组合索引的后面。 对于…

vue+threeJS 大理石贴图

嗨&#xff0c;我是小路。今天主要和大家分享的主题是“vuethreeJS 大理石贴图”。 通过 Vue 3 和 Three.js 实现大理石纹理效果&#xff0c;并将这种技术应用于产品展示、虚拟展览、甚至是互动游戏之中&#xff0c;其潜力无穷。今天主要介绍基础的大理石贴图。 vueth…

依赖倒转原则:Java 架构设计的核心准则

在软件开发的漫长演进历程中&#xff0c;设计原则如同灯塔般指引着工程师构建可维护、可扩展的系统。其中&#xff0c;依赖倒转原则&#xff08;Dependency Inversion Principle, DIP&#xff09;作为面向对象设计的五大核心原则之一&#xff0c;深刻影响着系统架构的稳定性与灵…

使用Frp搭建内网穿透,外网也可以访问本地电脑。

一、准备 1、服务器&#xff1a;需要一台外网可以访问的服务器&#xff0c;不在乎配置&#xff0c;宽带好就行。我用的是linux服务器。&#xff08;一般买一个1核1g的云服务器就行&#xff09;&#xff0c;因为配置高的服务器贵&#xff0c;所以这是个择中办法。 2、客户端&a…

Spyglass:跨时钟域同步(同步使能)

相关阅读 Spyglasshttps://blog.csdn.net/weixin_45791458/category_12828934.html?spm1001.2014.3001.5482 简介 同步使能方案主要用于数据信号跨时钟域同步&#xff0c;该方案将一个控制信号同步至目标时钟域并用其作为数据信号的捕获触发器的使能信号&#xff0c;如图1所示…

人工智能 (AI) 在无线接入网络 (RAN) 中的变革性作用

随着电信行业向更智能、更高效的系统迈进&#xff0c;将 AI 集成到 RAN 中已不再是可有可无&#xff0c;而是至关重要。 随着 6G 时代的到来&#xff0c;人工智能 (AI) 有望降低运营成本&#xff0c;并带来更大的盈利机会。AI-RAN 正处于这一变革的前沿&#xff0c;在 RAN 环境…

多线程代码案例-2 阻塞队列

阻塞队列 通过数据结构的学习&#xff0c;我们都知道了队列是一种“先进先出”的数据结构。阻塞队列&#xff0c;是基于普通队列&#xff0c;做出扩展的一种特殊队列。 特点 1、线程安全的 2、具有阻塞功能&#xff1a;1、如果针对一个已经满了的队列进行入队列&#xff0c…

【笔记】记一次PyCharm的问题反馈

#工作记录 最近更新至 PyCharm 社区版的最新版本后&#xff0c;我遇到了多个影响使用体验的问题。令人感到不便的是&#xff0c;一些在旧版本中非常便捷的功能&#xff0c;在新版本中却变得操作复杂、不够直观。过去&#xff0c;我一直通过 PyCharm 内置的故障报告与反馈机制反…

学习以任务为中心的潜动作,随地采取行动

25年5月来自香港大学、OpenDriveLab 和智元机器人的论文“Learning to Act Anywhere with Task-centric Latent Actions”。 通用机器人应该在各种环境中高效运行。然而&#xff0c;大多数现有方法严重依赖于扩展动作标注数据来增强其能力。因此&#xff0c;它们通常局限于单一…

相关行业发展趋势写一个爬虫程序

前两篇我利用爬虫进行营销推广&#xff0c;并且写了一个品牌口碑爬虫的代码示例。现在根据转向行业发展趋势&#xff0c;可能是希望收集数据来分析市场动向、竞争对手动态或者新兴技术趋势。 技术实现方面&#xff0c;需要选择合适的工具和库。Python的requests和BeautifulSou…