02-Qt入门与项目结构.md 31 KB


title: Qt入门与项目结构 tags: [嵌入式Linux, Qt, QtCreator, qmake, pro文件, ui文件, QtDesigner, moc, qrc, IMX6ULL] created: 2026-09-18 updated: 2026-09-18

pdf_ref: "《【正点原子】I.MX6U嵌入式Qt开发指南V1.2》第三章 初识Qt、第四章 使用Qt Designer开发;例程 Embedded-Qt-Tutorial/Qt/01/01_hello_world、02_designer_example"

Qt入门与项目结构

💡 关联知识:[[05-Qt应用开发/01-C++基础与面向对象]](Qt 项目里的继承、虚函数、this 全部来自 C++)、[[05-Qt应用开发/03-信号与槽]](Qt Designer 里连接的信号槽,正是下一篇的主题);延伸阅读:[[编程学习项目/使用Qt和C++构造UI界面/1. Qt概述]]、[[编程学习项目/使用Qt和C++构造UI界面/2. 创建Qt项目]]

本篇解决"从零跑起一个 Qt 程序"的全部问题:Qt 到底是什么、和 Qt Creator 什么关系、怎么装、怎么新建项目、项目里每个文件是干嘛的、qmake && make 背后发生了什么。最后用 Qt Designer 做一个"点击按钮关闭窗口"的完整例子,并首次触碰信号与槽。

配置 Qt Creator 的中文输入法是新手最容易卡住的一步,本篇按原书流程完整保留。


1. Qt 是什么

1.1 Qt 的定位

Qt 是一个跨平台的 C++ 开发库,主要用来开发图形用户界面(Graphical User Interface,GUI)程序。但 GUI 并不是 Qt 的全部,它还内置了大量非界面能力:

能力类别 说明
图形界面 控件、布局、交互、绘图
多线程 QThread
数据库 Qt SQL
图像处理 QImageQPixmapQPainter
音频视频 Qt Multimedia
网络通信 QTcpSocketQUdpSocket
文件操作 QFileQTextStream

Qt 还存在 Python、Ruby、Perl 等脚本语言的绑定;支持的操作系统非常多,例如通用操作系统 Windows、Linux、Unix,智能手机系统 Android、iOS、WinPhone,嵌入式系统 QNX、VxWorks 等。

Qt 最让人喜欢的特性是跨平台:一份代码无需修改或只需小修改,就能在其他平台运行。

1.2 Qt 与 Qt Creator 的关系

⚠️ 来源说明:本节不属于《I.MX6U嵌入式Qt开发指南》内容,为扩展知识。

原书 3.1.1 小节仅列出标题未展开正文。这两个名字初学者最容易混淆:

名称 是什么 类比
Qt 跨平台 C++ 开发库(一堆 .so/.dll + 头文件 + 工具链) 相当于"语言的标准库"
Qt Creator 官方出品的 IDE(集成开发环境),用来写代码、编译、调试、设计界面 相当于"编辑器 + 构建器 + 调试器"

关系可以这样理解:Qt Creator 自带的 Qt Designer(UI 设计器)也只是它的一个功能模块,属于 Qt Creator,不要和 Qt 库混为一谈。没有 Qt Creator,用 vim + qmake + make 一样能开发 Qt 程序,只是没有可视化界面而已。

flowchart TB
    subgraph QtLib["Qt(开发库)"]
        Core["QtCore / QtGui / QtWidgets ..."]
        Tools["qmake / moc / uic / rcc"]
    end
    subgraph QTC["Qt Creator(IDE)"]
        Editor["代码编辑器"]
        Designer["Qt Designer(UI 设计器)"]
        Debug["调试器"]
        Build["构建与运行"]
    end
    QTC -->|调用| QtLib

1.3 Qt 能做什么

理论上你能想到的 App,Qt 基本都能做:WPS 这类大型桌面应用、Maya(3D 建模)、一些游戏内核都能用 Qt 实现,也可以快速开发音乐播放器。在嵌入式里,用 Qt 开发界面已几乎是主流,工控界面最常用,移动端界面(点菜机、温度采集显示、汽车仪表、速度显示)也开始用 Qt。

原书举例的界面有:暗黑主题音乐播放器、"炫酷车载音乐 APP 主界面"等。作者的提醒很实在:设计界面占用的时间可能是 70%,写程序占 30%,做好界面要有想法,最好有一点美工基础。

1.4 Qt/C++ 与 QML

  • QML 是在 Qt C++ 基础上拓展的声明式语言,Qt C++ 上使用的界面类基本都能拓展到 QML;不能拓展的也可以 QML 与 C++ 混用。
  • Qt QML 模块为 QML 开发提供框架;QML 本身不涉及显示部分,由 Qt Quick 模块承担显示。
  • Qt C++ 效率更高,在底层编写功能更突出;要做好看又功能强的界面,Qt C++ 与 QML 结合是必不可少的——QML 负责界面层,C++ 负责底层(文件读写、图像处理、多线程通信等)。
  • 低版本 Qt(如 Qt5.6 以下)QML 不够成熟,高版本(Qt5.7 以上)更成熟。C++ 依旧是 Qt 的主要编程语言,Qt5 也添加了很多新的 C++ API。

本教程以 Qt C++ 为主,QML 作为加分项。


2. 如何选择 Qt 版本(3.2)

选择版本的总原则:不要盲目追最新,选长期支持(LTS)版本

版本 说明
Qt4 / Qt5 信号槽写法有区别(Qt4 的旧写法本教程不讲解)
Qt5.6 / Qt5.9 Qt 长期支持版本(LTS,Long Term Support)
Qt5.12 LTS 版本,本教程以 Qt5.12.9 开发及实验
Qt6 理论上与 Qt5 兼容,但仍需时间普及;许多公司仍在用 Qt5 甚至 Qt4

几点说明:

  • Qt5.15 是截至原书成书时较新的 Qt5 版本。
  • Qt 官方曾把 Qt5.2~Qt5.8、Qt5.11 归档,老版本要到归档地址下载。
  • 程序写好后要长期运行在某个确定版本里,避免随意升级带来兼容性问题或重复移植。
  • 原书成书时 Qt 官网部分地址国内访问受限,教程使用离线安装包 Qt5.12.9(位于资料网盘)。

⚠️ 来源说明:本节不属于《I.MX6U嵌入式Qt开发指南》内容,为扩展知识。

在线安装早已改为 Qt 官方 Online Installer,离线包路径也可能变化;下载链接会变动,选版本原则(LTS、固定版本)仍然适用。


3. 安装 Qt

3.1 Windows 下安装概要(3.3)

流程概括为:登录 Qt 帐号 → 同意开源许可(开源版遵循 GPLv2 / GPLv3 / LGPLv3)→ 修改安装目录 → 选择组件 → 安装 → 完成时勾选启动 Qt Creator。

Windows 组件选择要点:

组件 说明
MSVC 微软 VC 编译器,需要额外安装 VC 相关库
MinGW Minimalist GNU on Windows,可在 GNU/Linux 与 Windows 上生成 Windows 程序,教程只勾选 MinGW
Android / ARM 等 做嵌入式交叉编译时才需要
Sources Qt 源码,可按需选择
Source 以下 Qt 的各个模块,可按需勾选

安装完成后打开 Qt Creator 即可。

3.2 Linux 下安装(3.4)

在 Ubuntu 上下载 .run 安装包,赋予可执行权限后以 sudo 安装,默认装到 /opt 目录:

# 下载(原书给的链接,实际可能已失效,使用离线包即可)
wget http://download.qt.io/archive/qt/5.12/5.12.9/qt-opensource-linux-x64-5.12.9.run

# 赋予可执行权限
chmod +x qt-opensource-linux-x64-5.12.9.run

# 以 sudo 安装,这样会安装到 /opt 目录下
sudo ./qt-opensource-linux-x64-5.12.9.run

安装界面与 Windows 一致,选择默认安装目录即可。安装组件时,务必勾选 Desktop Qt5.12.9 GCC 64bit,否则 Qt Creator 里检测不到编译工具(Kit)。

安装完成后,在左下角应用程序中心找到 Qt Creator 打开。

注意/opt 目录普通用户只有读权限,没有写权限。所以 Qt Creator 里打开自带示例时要选"复制项目并打开"。

3.3 配置 Qt Creator 中文输入(3.4.2)

Ubuntu 默认是英文环境,且需要中文输入法才能在 Qt Creator 里写中文注释。

第一步:配置 Ubuntu 中文环境

  1. 右上角点击设置图标 → 区域与语言 → 管理已安装的语言(install/Remove Languages…)。
  2. 在语言列表中选择"简体中文",点击 Apply。
  3. 重启或注销 Ubuntu。系统询问是否把系统文件夹名称也改成中文时,建议选择"否",保留英文名,便于终端操作。

第二步:配置中文输入法

  1. 在"区域与语言"的键盘输入法系统(Keyboard input method system)中,确认设置为 IBus(Ubuntu 默认即为 IBus,没改过就不用动)。
  2. 回到区域与语言处,检查"输入源"中是否有"中文(智能拼音)"。若没有,点击"+"添加输入源 → 汉语 → 中文(智能拼音),也可以按习惯选择五笔等 IBus 输入法。
  3. 让配置生效:建议重启 Ubuntu,防止环境未生效。

验证:在终端里切换到中文输入,能打出汉字即成功。中英文切换一般按 Win + 空格(不同 Ubuntu 版本可能不同)。之后在 Qt Creator 中即可用 IBus 拼音输入法输入中文。


4. Qt Creator 简单使用

4.1 界面组成(3.5.1)

启动 Qt Creator 后默认打开欢迎页面,左侧栏主要按钮:

区域 作用
欢迎 打开示例、最近项目、入门教程
编辑 写代码、编辑 .ui(切到设计器)
设计 UI 设计界面
调试 调试
项目 构建设置
帮助 Qt 官方文档,可搜索类、方法、信号与槽,是学习 Qt 最重要的资料

Qt Creator 自带很多示例。由于在 Ubuntu 里 Qt 安装在 /opt 下没有写权限,打开示例时要先选"复制项目并打开"。

菜单"帮助 → UI Tour"会介绍 Qt Creator 各组件,建议看一看(英文)。

4.2 设置(3.5.2)

顶部菜单"工具 → 选项"。常用设置项:

设置项 作用
Kits 显示编译工具(如 Desktop Qt5.12.9 GCC 64bit);也可在此配置 ARM 平台编译器,Qt 跨平台正靠不同平台的编译工具实现
环境 设置主题、语言等(默认即可)
文本编辑器 设置字体大小、颜色,以及关键字/字符串/注释的配色
构建和运行 常用的是设置项目的构建目录,其余默认即可

5. 第一个 Qt 程序(3.6)

5.1 新建项目

  1. 打开 Qt Creator,菜单"文件 → 新建文件或项目",快捷键 Ctrl + N(需在英文输入法下)。
  2. 模板选择 Application (Qt) → Qt Widgets Application。模板会把 .cpp.ui 等文件都快速创建好,无需手动一个个加。
  3. 项目名称输入 01_hello_world,选择项目路径(可勾选"设为默认的项目路径"),下一步。
  4. 构建系统选择 qmake(用 qmake 生成 Makefile 用于编译),下一步。
  5. 基类(Base class)选择 QMainWindow,勾选"Generate form"(生成 mainwindow.ui),下一步。
  6. 勾选编译器(安装组件时选的那个,编译出 Ubuntu 上运行的程序),下一步。
  7. 版本控制选择"无",点击完成。

基类怎么选

基类 说明 适用场景
QMainWindow 主窗口类,带主菜单栏、工具栏、状态栏 桌面式主窗口程序
QWidget 可视界面类的基类;QMainWindow 也是由 QWidget 继承封装而来,功能更少 嵌入式常用(嵌入式一般不需要标题栏、状态栏)
QDialog 对话框类 较少作为主基类

5.2 项目文件介绍(3.6.2)

新建项目后,左侧项目文件结构分组如下:

文件/分组 内容
01_hello_world.pro 项目管理文件,加入/删除文件时 Qt Creator 会自动修改它;有时需手动打开添加设置项
Header 分组 项目内所有头文件 *.h
Source 分组 项目内所有 C++ 源码 *.cpp
Forms 分组 项目内所有界面文件 *.ui(XML 描述,编译时生成相应 cpp 文件供交叉编译器编译)

项目名以粗体显示表示它是活动项目

5.2.1 项目文件 *.pro(3.6.2.1)

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    main.cpp \
    mainwindow.cpp

HEADERS += \
    mainwindow.h

FORMS += \
    mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

逐行解释:

  • 第 1 行:添加 Qt 支持的模块,coregui 是 Qt 默认设置。
  • 第 3 行:比较 Qt5 版本,如果是 Qt5,applicationQtWidgets 中,因此要加上 widgets 库。
  • 第 5 行:配置使用 C++11。
  • 第 11 行:添加 QT_DEPRECATED_WARNINGS 定义(使用被标记为过时的 API 时给出警告)。
  • 第 18 行:SOURCES 下的源文件列表。
  • 第 22 行:HEADERS 下的头文件列表。
  • 第 25 行:FORMS 下的 ui 界面文件列表;若项目不需要 ui 文件,这里留空即可。
  • 第 28 行起:部署默认规则。qnx 判断是不是 qnx 操作系统,赋值 target.path;如果是 unix 但不是 android,赋值 /opt/$${TARGET}/bin;若 target.path 非空则 INSTALLS += target

若要修改生成的可执行文件名,可加 TARGET = xxx;否则 TARGET 默认取项目名。

5.2.2 样式文件 *.ui(3.6.2.2)

mainwindow.ui 是 XML 文件,由 Qt Designer 生成,不要手动编辑,只能通过图形界面修改属性:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>800</width>
    <height>600</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QLabel" name="label">
    <property name="geometry">
     <rect>
      <x>260</x>
      <y>160</y>
      <width>101</width>
      <height>17</height>
     </rect>
    </property>
    <property name="text">
     <string>Hello World!</string>
    </property>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>800</width>
     <height>28</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

双击 .ui 文件进入设计界面,主要区域:

区域 说明
① 控件栏 各种控件;上方 Filter 输入首字母可快速定位
② 设计窗体 显示窗口程序,默认 MainWindow 带菜单栏和状态栏
③ 对象栏 ②中用到的对象都在此显示(树状结构)
④ 属性栏 选中③中对象后,在此编辑其属性(位置、大小、文字、颜色、字体等)

5.2.3 头文件 *.h(3.6.2.3)

mainwindow.h 一般有一个对应的 mainwindow.cpp.h类的声明.cpp类的实现,这与前面 C++ 的知识一致。

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

逐行解释:

  • 第 7 行:定义命名空间 Ui,里面有一个类 MainWindow,它和第 10 行的 MainWindow 不是同一个。本文件里的 MainWindow 类有一个成员 *ui,指向 Ui::MainWindow 的指针,这都是为了使用 .ui 文件设计界面。
  • 第 12 行:Q_OBJECT 是一个宏,由 Qt 处理(moc),这是 Qt 对 C++ 的扩展;所有用到信号与槽的类都要加这个宏

5.2.4 源文件 *.cpp(3.6.2.4)

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

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

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

逐行解释:

  • 第 2 行:ui_mainwindow.hQt 根据 .ui 文件自动生成的,构建/编译后才在 debug/release 目录出现。
  • 第 4~6 行:构造函数用初始化列表,ui(new Ui::MainWindow) 是初始化成员的方法。
  • 第 8 行:ui->setupUi(this); 进行界面初始化,把 this(MainWindow 本身)作为参数传入,ui 里的对象以 this 为父对象,所有子对象都显示在 MainWindow 里。要使用 ui 里的对象,代码必须写在 ui->setupUi(this) 之后
  • 第 13 行:析构函数里 delete ui在 Qt 里需要在析构函数 delete 的对象,一般是 new 出来且没有父对象的对象(有父对象的会由父对象自动释放)。

main.cpp

#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

逐行解释:

  • 第 3 行:包含 QApplication 类定义。每个使用 Qt 的应用程序都必须有一个 QApplication 对象,它管理各种应用程序的广泛资源(如默认字体和光标)。
  • 第 5 行:main() 是程序入口。argc 是命令行变量数量,argv 是命令行变量数组。
  • 第 7 行:创建 QApplication 对象 a,处理命令行变量。
  • 第 8 行:创建 MainWindow 对象 w
  • 第 9 行:w.show(),程序界面才能显示。
  • 第 10 行:把控制转交给 Qt,应用程序退出时 exec() 返回。exec() 中 Qt 接受并处理用户和系统事件,并传递给适当的窗口部件。

5.3 修改 ui 文件显示 Hello World(3.6.3)

  1. 双击 mainwindow.ui 进入 UI 设计器。
  2. 在左侧控件栏找到 Label 控件(在 "Display Widgets" 分组下)。
  3. 把 Label 拖到中间的设计窗体。
  4. 在对象栏选中 label,在属性栏找到 text 属性,修改为 Hello World!。也可直接双击 Label 修改文本。
  5. 保存。

5.4 项目编译、调试、运行(3.6.4)

编译运行

  • 点击左下角绿色三角按钮,或按 Ctrl + R(编译且运行)。
  • 编译输出窗口可以看到编译警告、错误、链接和相关编译器过程。
  • 第一次编译常见错误 Cannot find -lGL:Qt5.0 的库默认链接到 OpenGL,而 Ubuntu 没装 OpenGL。解决:

    sudo apt-get install libglu1-mesa-dev
    

若还有其他报错,回到 C++ 环境设置补装相应库——Qt 也依赖 C++ 环境

调试:关闭已运行的窗口,在代码里右键设置断点,点击左下角带 Debug 的绿色三角按钮即可调试。简单程序一般不需要,但可用来观察 Qt 程序运行流程。


6. 构建流程与项目结构总结

6.1 qmake 构建链路

.pro 文件本身不是 Makefile,qmake 先把它翻译成 Makefile,再由 make 驱动编译器。过程中还涉及三个工具:

工具 输入 输出 作用
qmake *.pro Makefile 根据工程配置生成构建规则
moc Q_OBJECT*.h moc_*.cpp 元对象编译器,实现信号槽等元对象能力
uic *.ui ui_*.h 把界面 XML 转成 C++ 头文件
rcc *.qrc qrc_*.cpp 把资源文件编译进程序
flowchart LR
    PRO["*.pro"] -->|qmake| MK["Makefile"]
    UI["*.ui"] -->|uic| UIH["ui_mainwindow.h"]
    H["mainwindow.h(Q_OBJECT)"] -->|moc| MOC["moc_mainwindow.cpp"]
    QRC["*.qrc"] -->|rcc| RCC["qrc_resources.cpp"]
    MK -->|make| BIN["可执行程序"]
    UIH --> BIN
    MOC --> BIN
    RCC --> BIN
    CPP["*.cpp"] --> BIN

6.2 命令行构建步骤

不打开 Qt Creator 时,用 qmake && make 即可构建:

cd 01_hello_world
/opt/Qt5.12.9/5.12.9/gcc_64/bin/qmake 01_hello_world.pro   # 生成 Makefile
make                                                       # 编译链接
./01_hello_world                                           # 运行

⚠️ 来源说明:本节不属于《I.MX6U嵌入式Qt开发指南》内容,为扩展知识。

Qt 安装路径随版本和安装方式变化,可用 which qmakeqmake -v 确认;交叉编译时把 qmake 换成目标平台的 qmake 即可(见 [[05-Qt应用开发/08-嵌入式Qt交叉编译与项目实战]])。

6.3 项目文件一览

文件 由谁生成 是否手改 作用
*.pro Qt Creator 可小改 工程配置:模块、源文件、编译选项
*.ui Qt Designer 不手改 界面 XML,uic 转成 ui_*.h
*.h 开发者 类声明、信号槽声明
*.cpp 开发者 类实现
ui_*.h uic 不手改 构建时生成,位于 build 目录
moc_*.cpp moc 不手改 构建时生成
*.qrc 开发者 可改 资源索引,rcc 编译进程序

6.4 资源文件 .qrc

⚠️ 来源说明:本节不属于《I.MX6U嵌入式Qt开发指南》内容,为扩展知识。

.qrc 会在后续控件章节(第七章)的例程中实际使用。

Qt 资源系统(The Qt Resource System)把图片、图标、字体、翻译文件等打包进可执行文件,程序运行时不再依赖外部文件路径,非常适合嵌入式。资源索引文件以 .qrc 为后缀,也是 XML 格式,例如某控件例程的 res.qrc

<RCC>
    <qresource prefix="/">
        <file>images/openedv.png</file>
    </qresource>
</RCC>
  • <qresource prefix="/">:资源在程序内的访问前缀。
  • <file>images/openedv.png</file>:相对于 .qrc 文件的资源路径。
  • 程序中用 ":/images/openedv.png" 访问。
  • 新加入资源后,需要在 .pro 里声明 RESOURCES += res.qrc(Qt Creator 添加资源时通常会自动写入),然后 rcc 会生成 qrc_*.cpp 参与编译。

7. 使用 Qt Designer 开发(第四章)

Qt Designer 是 Qt Creator 的一个功能,也叫 UI 设计器。它以"连接信号与槽"为例展示可视化开发流程。

7.1 在 UI 文件添加一个按钮(4.1.1)

新建项目 02_designer_example(步骤同 3.6)。在左侧找到 Push Button,拖到中间窗体;在属性栏把它的 text 属性改为"关闭程序"。

7.2 在 UI 文件里连接信号与槽(4.1.2)

先建立直观认识:信号是对象在特定情况下发出的"事件";是信号发出时被触发执行的函数。在 Qt 里要想让事件做出对应动作,就必须用信号与槽(下一章详述)。

方法一:在 UI 设计器里可视化连接

  1. 点击设计器顶部的"信号槽连接"按钮进入连接模式(退出点它左边的按钮)。
  2. 选中"关闭程序"按钮,按住鼠标向外拖动,出现信号槽连接符号。
  3. 左侧选择 pushButtonclicked() 信号,右侧选择 MainWindowclose() 槽,完成连接。
  4. 切回"编辑部件"模式。

含义:单击"关闭程序"按钮时发出 clicked() 信号,触发 MainWindowclose() 槽,从而关闭程序。

连接保存在 .ui 文件的 <connections> 节点里:

 <connections>
  <connection>
   <sender>pushButton</sender>
   <signal>clicked()</signal>
   <receiver>MainWindow</receiver>
   <slot>close()</slot>
  </connection>
 </connections>

编译后这些连接会变成 ui_mainwindow.hsetupUi() 里的 QObject::connect(...) 语句。

方法二:右键"转到槽"

  1. 选中"关闭程序"按钮,右键 → "转到槽"。
  2. 弹出窗口选择信号 clicked()。注意这个 clicked() 并不属于 QPushButton 而是属于 QAbstractButtonQPushButton 继承下来即可使用——这正是 C++ 继承在 Qt 里的体现,根本不用重写 clicked() 事件
  3. 点击 OK 后,Qt Creator 自动在 mainwindow.h 声明槽函数,并在 mainwindow.cpp 生成函数框架。
  4. 在生成的 on_pushButton_clicked() 槽函数里写 this->close();

7.3 完整例程源码

02_designer_example.pro(与 01 例程结构相同):

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

DEFINES += QT_DEPRECATED_WARNINGS

SOURCES += \
    main.cpp \
    mainwindow.cpp

HEADERS += \
    mainwindow.h

FORMS += \
    mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

mainwindow.ui(含按钮与信号槽连接):

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>800</width>
    <height>600</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QPushButton" name="pushButton">
    <property name="geometry">
     <rect>
      <x>260</x>
      <y>150</y>
      <width>89</width>
      <height>25</height>
     </rect>
    </property>
    <property name="text">
     <string>关闭程序</string>
    </property>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>800</width>
     <height>28</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections>
  <connection>
   <sender>pushButton</sender>
   <signal>clicked()</signal>
   <receiver>MainWindow</receiver>
   <slot>close()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>325</x>
     <y>184</y>
    </hint>
    <hint type="destinationlabel">
     <x>379</x>
     <y>106</y>
    </hint>
   </hints>
  </connection>
 </connections>
</ui>

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private slots:
    void on_pushButton_clicked();

private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

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

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


void MainWindow::on_pushButton_clicked()
{
     this->close();
}

main.cpp(与 01 例程完全一致):

#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

7.4 编译及运行(4.1.3)

Ctrl + R 或点击左下角绿色三角编译运行。点击"关闭程序"按钮,整个程序关闭退出。

此时会浮现两个问题,答案在下一篇:

  1. 方法一用 Designer 可视化连接,连接到底写在哪里?——编译后写在生成的 ui_mainwindow.hsetupUi() 里,即 QObject::connect(pushButton, SIGNAL(clicked()), MainWindow, SLOT(close()));
  2. 方法二只是写了个 on_pushButton_clicked() 槽函数,为什么会被自动触发?——Qt 通过 moc 元对象系统 + 命名约定自动连接,这就是 Qt 信号槽机制。

8. 跨平台对比

⚠️ 来源说明:本节不属于《I.MX6U嵌入式Qt开发指南》内容,为扩展知识。

维度 Ubuntu(本教程) Windows I.MX6ULL(嵌入式)
安装方式 .run 安装到 /opt 官方 installer,选 MinGW 交叉编译工具链 + 目标板 Qt 库
编译器 gcc/g++ MinGW 的 g++ 或 MSVC arm-linux-gnueabihf-g++
Qt 版本 Qt5.12.9 LTS Qt5.12.9 与目标板根文件系统 Qt 版本一致
基类选择 QMainWindowQWidget 常用 QWidget(无标题栏/状态栏)
.pro 写法 三端基本一致 三端基本一致 只需切换 qmake/Kit
运行方式 ./app 双击 exe 拷贝到开发板 ./app
显示后端 X11/Wayland Windows 原生 LinuxFB / EGLFS(无桌面)

结论:.pro/.ui/.h/.cpp 工程结构在三端完全通用,跨平台的关键只是切换 Kit(编译器 + qmake + Qt 库)。嵌入式的特殊点在于常无窗口系统、常用 QWidget 基类。


9. 面试精选

⚠️ 来源说明:本节不属于《I.MX6U嵌入式Qt开发指南》内容,为扩展知识。

Q1:Qt 和 Qt Creator 有什么区别?Qt Designer 又是什么?

:Qt 是跨平台的 C++ 开发库,提供界面与非界面(网络、数据库、多媒体等)能力;Qt Creator 是官方 IDE,用来编写、构建、调试项目。Qt Designer(UI 设计器)是 Qt Creator 的一个功能模块,用于可视化拖拽设计 .ui 界面文件。三者层次不同:库、IDE、IDE 内的设计器。

Q2:一个 Qt Widgets 项目里各个文件的作用分别是什么?

.pro 是工程文件,记录 Qt 模块、源文件/头文件/界面文件和编译选项,qmake 据此生成 Makefile;.ui 是 Qt Designer 生成的界面 XML,由 uic 转成 ui_*.h.h 放类声明与信号槽声明;.cpp 放类实现;main.cpp 创建 QApplication 与主窗口并调用 exec() 进入事件循环。构建时还会生成 moc_*.cpp(元对象代码)和 qrc_*.cpp(资源)。

Q3:main.cppQApplication a(argc, argv); ... return a.exec(); 各自的作用?

:每个 Qt 应用必须有且通常只有一个 QApplication 对象,它管理应用级资源(字体、光标等)并处理命令行参数。创建主窗口并 show() 后,a.exec() 把控制交给 Qt,进入事件循环,不断接收并分发用户和系统事件到相应窗口部件;当应用退出时 exec() 返回其状态码并结束 main()

Q4:.ui 文件和 ui_*.h 有什么关系?信号槽连接写在哪里?

.ui 是 XML 格式的界面描述文件,不能手动编辑内容,由 Qt Designer 维护;构建时 uic 工具根据 .ui 生成 ui_*.h(如 ui_mainwindow.h),里面定义 Ui::MainWindow 类并在 setupUi() 中创建控件。用 Designer 可视化方式连接的信号槽会以 QObject::connect(...) 的形式出现在生成的 setupUi() 里,所以运行期连接是真实存在的。

Q5:为什么嵌入式 Qt 项目常选 QWidget 而不是 QMainWindow 作基类?

QMainWindow 自带主菜单栏、工具栏、状态栏等桌面式主窗口结构,而 QWidget 是更基础的可视界面类(QMainWindow 本身也由 QWidget 继承封装而来)。嵌入式设备通常全屏显示、没有窗口边框和系统标题栏,也不需要菜单/状态栏,因此用更轻量、更自由的 QWidget 作为基类更合适。


内容来源:《I.MX6U嵌入式Qt开发指南V1.2》第三章 初识Qt、第四章 使用Qt Designer开发,以及正点原子 Qt 开发指南例程源码 Embedded-Qt-Tutorial/Qt/01/01_hello_world02_designer_example