Qt 入门:环境配置与核心机制

Qt
2.2k 词

Qt 是一套跨平台的 C++ 应用程序开发库。与 MFC 不同,Qt 支持 Windows、Linux、macOS 甚至嵌入式平台。

环境搭建

安装

1
2
3
4
5
6
# Qt Designer
sudo apt-get install qt5-default qttools5-dev-tools
designer # 启动

# PyQt5(可选)
sudo pip3 install pyqt5

CLion 不能打开 .ui 文件,需要借助 Qt Designer。两者可以同时部署给同一个项目——把 build 文件夹设为同一个,共同读取 CMakeLists.txt。

项目结构

1
2
3
4
5
6
7
project/
├── Sources/ # .cpp 源文件
│ └── main.cpp
├── Headers/ # .h 头文件
├── Forms/ # .ui 界面文件
├── lib/ # 第三方库 .dll/.a
└── include/ # 第三方库头文件

开发目录不要含中文路径。

元对象系统(Meta-Object System)

Qt 对标准 C++ 进行了扩展,通过元对象编译器(MOC)将 Qt 特性代码转化为标准 C++ 后再编译。

三个基础

  • QObject 是所有使用元对象系统的类的基类
  • 在类的 private 部分声明 Q_OBJECT
  • MOC 为每个 QObject 子类生成必要代码

动态类型转换

1
2
3
4
5
6
7
8
9
10
QObject → QWidget → QMyWidget

// 基类指针指向派生类对象
QObject *obj = new QMyWidget;

// 向上转型:安全
QWidget *w = qobject_cast<QWidget*>(obj);

// 判断类型
timer->inherits("QTimer"); // true/false

信号与槽

信号与槽是 Qt 最核心的通信机制,优势在于松散耦合——发送者和接收者通过 connect 连接,彼此不依赖。

基本用法

1
2
3
4
5
// 旧式语法
QObject::connect(sender, SIGNAL(clicked()), receiver, SLOT(onClicked()));

// 推荐:新式语法(编译期检查)
connect(sender, &QPushButton::clicked, receiver, &MyClass::onClicked);
  • 一个信号可以连接多个槽
  • 多个信号可以连接同一个槽
  • 信号和槽的参数类型必须匹配

Lambda 表达式

Lambda 用于封装短小的匿名函数,在 Qt 中常作为槽函数使用。

语法

1
[capture](params) mutable -> return_type { body }
部分 说明
[] 捕获列表,Lambda 引出符
() 参数列表(可省略)
mutable 取消 const 限制(可省略)
-> type 返回类型(可省略,编译器推导)
{} 函数体

捕获列表

1
2
3
4
5
6
[]         // 不捕获任何变量
[var] // 值传递捕获 var
[&var] // 引用传递捕获 var
[=] // 值传递捕获所有变量
[&] // 引用传递捕获所有变量
[=, &var] // 除 var 引用外,其余值传递

Qt 中的典型用法

1
2
3
connect(btn, &QPushButton::clicked, this, [this]() {
label->setText("Button clicked!");
});

Lambda 本质是编译器生成一个匿名类的匿名对象,重载了 operator()

对象树与内存管理

Qt 的对象呈树状结构。关键规则:设置父对象后,父对象销毁时会自动释放所有子对象

1
2
3
4
5
6
QPushButton *btn = new QPushButton(this);  // this 作为父对象
btn->move(100, 200); // 相对父窗口的坐标

// 也可以后设置
QPushButton *btn = new QPushButton;
btn->setParent(this);

窗口坐标

1
2
3
4
5
resize(800, 600);                    // 重置窗口大小
setFixedSize(400, 300); // 固定窗口大小
setWindowTitle("My Window"); // 设置窗口标题
btn->move(x, y); // 相对父窗口移动
btn->setGeometry(100, 300, w, h); // 绝对屏幕坐标

CMakeLists.txt 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cmake_minimum_required(VERSION 3.5)
project(MyQtApp)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_AUTOMOC ON) # 自动调用 MOC
set(CMAKE_AUTORCC ON) # 自动处理 .qrc 资源文件

find_package(Qt5 REQUIRED COMPONENTS Widgets)

add_executable(${PROJECT_NAME}
main.cpp
mainwindow.cpp
)

target_link_libraries(${PROJECT_NAME} Qt5::Widgets)