跳到主要内容

第一个 Qt 程序

本节将带你创建第一个 Qt 应用程序,了解 Qt 项目的基本结构和工作原理。

创建项目

使用 Qt Creator

  1. 打开 Qt Creator,选择"文件" → "新建文件或项目"
  2. 选择"Application (Qt)" → "Qt Widgets Application"
  3. 设置项目名称(如 FirstApp)和保存路径
  4. 构建系统选择 CMake(现代 Qt 项目的标准选择)
  5. 类信息页面保持默认(基类为 QMainWindow
  6. 完成创建

项目结构解析

创建完成后,你会看到以下文件结构:

FirstApp/
├── CMakeLists.txt # CMake 构建配置
├── main.cpp # 程序入口点
├── mainwindow.h # 主窗口类声明
├── mainwindow.cpp # 主窗口类实现
└── mainwindow.ui # UI 设计文件(XML)

让我们逐一了解这些文件的作用。

程序入口 main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
// 1. 创建 QApplication 对象
// 每个 Qt GUI 程序必须有且只有一个 QApplication
// 它管理应用程序的全局资源、事件循环等
QApplication app(argc, argv);

// 2. 创建主窗口对象
MainWindow window;

// 3. 显示窗口
window.show();

// 4. 进入事件循环
// exec() 会阻塞,直到应用程序退出
// 它不断处理用户输入、定时器、网络事件等
return app.exec();
}

代码解读

QApplication 是 Qt 应用程序的核心类:

  • 管理应用程序的全局设置
  • 处理事件循环(Event Loop)
  • 管理字体、光标、剪贴板等全局资源
  • 解析命令行参数
事件循环的重要性

Qt 是基于事件驱动的框架。exec() 启动的事件循环不断从系统获取事件(鼠标点击、键盘输入、定时器等),并分发给相应的对象处理。没有事件循环,GUI 就无法响应用户操作。

主窗口类

mainwindow.h(头文件)

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow> // Qt 主窗口基类

// 前向声明 UI 类
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

// 继承自 QMainWindow
class MainWindow : public QMainWindow
{
// 宏:启用 Qt 的元对象系统
// 提供信号槽、运行时类型信息等特性
Q_OBJECT

public:
// 构造函数,parent 用于指定父窗口
MainWindow(QWidget *parent = nullptr);

// 析构函数
~MainWindow();

private:
// UI 类指针,用于访问界面元素
Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

关键概念解释

Q_OBJECT 宏

这是 Qt 的核心宏,必须在所有使用信号槽、属性系统或需要运行时类型信息的类声明中添加。它会在编译时生成额外的元对象代码(moc 处理)。

父对象系统

Qt 使用对象树管理内存。当创建对象时传入 parent 参数:

  • 父对象销毁时会自动销毁所有子对象
  • 子对象无需手动 delete
  • 这是 Qt 自动内存管理的基础

mainwindow.cpp(实现文件)

#include "mainwindow.h"
#include "ui_mainwindow.h" // 由 .ui 文件生成的头文件

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent) // 调用基类构造函数
, ui(new Ui::MainWindow) // 创建 UI 对象
{
// 设置 UI
// 这会创建所有在 Designer 中设计的控件
ui->setupUi(this);

// TODO: 在这里添加自定义初始化代码
}

MainWindow::~MainWindow()
{
// 释放 UI 对象
delete ui;
}

UI 设计文件

mainwindow.ui 是一个 XML 文件,描述界面布局。Qt Creator 提供可视化编辑器(Qt Designer)来编辑它。

在 Designer 中添加控件

  1. 双击 mainwindow.ui 打开设计器
  2. 从左侧控件面板拖拽控件到窗口:
    • 拖一个 Label(标签)到中央区域
    • 拖一个 Push Button(按钮)到标签下方
  3. 在右侧属性面板修改控件属性:
    • Label 的 text 改为 "Hello, Qt!"
    • Button 的 text 改为 "Click Me"
  4. Ctrl+S 保存

理解 UI 文件

虽然可以用可视化工具编辑,但了解 UI 文件的结构很有帮助:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<widget class="QWidget" name="centralwidget">
<widget class="QLabel" name="label">
<property name="text">
<string>Hello, Qt!</string>
</property>
</widget>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>Click Me</string>
</property>
</widget>
</widget>
</widget>
</ui>

编译时,uic(UI Compiler)会将这个 XML 转换为 C++ 头文件 ui_mainwindow.h

添加交互功能

让我们为按钮添加点击事件处理。

方式一:使用信号槽(推荐)

mainwindow.h 中添加槽函数声明:

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();

private slots: // 槽函数声明区域
void onButtonClicked();

private:
Ui::MainWindow *ui;
};

mainwindow.cpp 中实现并连接:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox> // 消息框

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);

// 连接信号和槽
// 当按钮被点击时,调用 onButtonClicked 函数
connect(ui->pushButton, &QPushButton::clicked,
this, &MainWindow::onButtonClicked);
}

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

void MainWindow::onButtonClicked()
{
// 显示消息框
QMessageBox::information(this, "消息", "Hello, Qt!");
}

方式二:自动连接(命名约定)

Qt 支持按命名约定自动连接信号槽。将槽函数命名为 on_<控件名>_<信号名>

private slots:
void on_pushButton_clicked(); // 自动连接

然后在构造函数中不需要手动 connect,Qt 会自动找到并连接这个槽函数。

自动连接的注意事项

自动连接功能需要在 setupUi 之后调用 QMetaObject::connectSlotsByName(this),而 setupUi 内部已经调用了这个函数,所以直接使用命名约定即可。但要注意命名必须完全匹配(区分大小写)。

CMakeLists.txt 解析

cmake_minimum_required(VERSION 3.16)
project(FirstApp VERSION 1.0 LANGUAGES CXX)

# C++ 标准设置
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Qt 特有的设置
set(CMAKE_AUTOMOC ON) # 自动处理 moc(元对象编译器)
set(CMAKE_AUTORCC ON) # 自动处理资源文件
set(CMAKE_AUTOUIC ON) # 自动处理 UI 文件

# 查找 Qt 包
find_package(Qt6 REQUIRED COMPONENTS
Core # 核心非 GUI 功能
Gui # GUI 基础功能
Widgets # 桌面控件
)

# 创建可执行文件
add_executable(FirstApp
main.cpp
mainwindow.cpp
mainwindow.h
mainwindow.ui
)

# 链接 Qt 库
target_link_libraries(FirstApp PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)

关键设置说明

设置说明
CMAKE_AUTOMOC ON自动扫描头文件中的 Q_OBJECT 宏,运行 moc 生成元对象代码
CMAKE_AUTOUIC ON自动将 .ui 文件编译为 C++ 头文件
CMAKE_AUTORCC ON自动将资源文件(.qrc)编译进可执行文件

运行程序

在 Qt Creator 中

点击左下角的绿色运行按钮,或按 Ctrl+R

命令行方式

# 创建构建目录
mkdir build && cd build

# 配置
cmake ..

# 编译
cmake --build .

# 运行(Linux/macOS)
./FirstApp

# 运行(Windows)
FirstApp.exe

练习

  1. 修改窗口标题:在构造函数中使用 setWindowTitle("我的第一个 Qt 程序")

  2. 调整窗口大小:使用 resize(800, 600) 设置窗口尺寸

  3. 添加更多控件

    • 添加一个 QLineEdit(输入框)
    • 点击按钮时,将输入框的内容显示在消息框中

    提示代码:

    void MainWindow::onButtonClicked()
    {
    QString text = ui->lineEdit->text(); // 获取输入框文本
    QMessageBox::information(this, "输入内容", text);
    }
  4. 使用布局:在 Designer 中将控件放入 QVBoxLayout(垂直布局),使窗口缩放时控件自动调整位置

下一步

现在你已经了解了 Qt 程序的基本结构。接下来学习 Qt 核心概念,深入理解信号槽机制、元对象系统和事件循环。