Qt-01:创建一个项目
文章目录
推荐:https://blog.csdn.net/m0_65635427/article/details/130780280
Qt-01:创建一个项目
创建一个项目的具体方式
双击打开 Qt Creater,新建一个 Qt 项目
项目路径和文件名均不能带中文
选择 qmake 构建
选择窗口继承类型
Class name 是自定义类,需要继承 Base class;
Header file 和 Source file 是窗口类对应的头文件和源文件;
Form file 是 ui 文件,如果勾选了 Generate form 就会生成 ui 文件,可以很方便的拖拽控件。
Base class 有三类:
- QMainWindow 是 Qt 框架中用于创建主窗口的基类,提供标准的应用程序主窗口结构。包含菜单栏(QMenuBar)、工具栏(QToolBar)、状态栏(QStatusBar)以及中心部件(Central Widget)等预定义区域,适合构建复杂的桌面应用程序界面。支持多文档界面(MDI)和停靠窗口(QDockWidget)的集成。
- QWidget 是 Qt 中所有用户界面对象的基类,作为其他窗口部件的父类,提供基础的绘制、事件处理和布局功能。QWidget 可以单独作为顶级窗口(如对话框)或嵌套在其他部件中。不包含 QMainWindow 的预定义布局结构,但灵活性更高,适合自定义简单界面或子部件。
- QDialog 是用于创建对话框的基类,通常作为临时窗口与用户交互。分为模态(阻塞父窗口)和非模态(非阻塞)两种模式。内置标准按钮布局(如 QDialogButtonBox),支持扩展和返回值(exec())。常见子类包括 QFileDialog、QMessageBox 等预定义对话框。
可以自行配置语言,默认是系统配置
选择构建套件和模式
在软件开发中,常见的构建套件(Build Kit)模式包括 Debug、Release 和 Profile,它们的主要区别在于编译配置、优化级别和附加工具的启用情况,适用于不同的开发阶段。
- Debug 模式主要用于开发和调试阶段。通常关闭编译器优化(如
-O0),保留完整的符号信息,便于调试。启用断言(assert)、调试日志和完整的堆栈跟踪。运行速度较慢,但便于定位问题。生成的二进制文件较大,包含调试符号,适用于开发过程中单步调试、崩溃分析。 - Release 模式用于最终发布的生产环境。启用最高级别优化(如
-O2或-O3),可能移除冗余代码。关闭断言和调试日志,减少运行时开销。运行速度最快,资源占用低。二进制文件更小,可能剥离调试符号,适用于交付用户或部署到生产服务器。 - Profile 模式是性能分析和优化阶段,与 Release 类似,但保留部分符号信息(如函数名)。支持性能分析工具(如 Profiler),可收集 CPU、内存等指标,接近 Release,但可能有轻微开销。代码体积介于 Debug 和 Release 之间。适用于定位性能瓶颈或内存泄漏。
根据需求选择模式:开发用 Debug,测试性能用 Profile,最终部署用 Release。
生成相应文件
项目生成完毕,可以(Ctrl + R)运行出如下结果。
- main.cpp
#include "widget.h"
#include <QApplication> // 包含一个应用程序类的头文件
int main(int argc, char *argv[])
{
QApplication a(argc, argv); // 应用程序对象,在Qt中,有且仅有一个
Widget w; // 窗口对象,Widget父类 -> QWidget
w.show(); // 窗口对象,默认不会显示,必须调用show方法
return a.exec(); // 让应用程序对象进入消息循环,应用程序就阻塞在这里
}
- 01.pro
QT += core gui # Qt包含的模块 core 和 gui
# 如果使用Qt版本大于Qt4,需要添加 widgets 模块
# 因为在Qt4中widgets是包含在gui模块中的,Qt5后就将widgets从gui模块中独立出来了
# 窗口程序开发必须包含 widgets 模块
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
# 使用c++17的新特性
CONFIG += c++17
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000
# disables all the APIs deprecated before Qt 6.0.0
SOURCES += \ # 指定源文件
main.cpp \
widget.cpp
HEADERS += \ # 指定头文件
widget.h
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
- widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
class Widget : public QWidget
{
Q_OBJECT // Q_OBJECT宏,允许类中使用信号和槽机制
public:
Widget(QWidget *parent = nullptr); // 构造函数
~Widget(); // 析构函数
};
#endif // WIDGET_H
- widget.cpp
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{}
Widget::~Widget() {}
软件界面、字体、编码等配置
设置界面颜色和系统语言

设置字体类型、大小和颜色

设置代码显示行号以及高亮当前行

设置文件编码

设置在终端运行

Makefile、make、qmake 的关系和作用
Makefile是一个文本文件,用于定义项目的编译规则和依赖关系。它包含一系列规则,每条规则指定如何从源文件生成目标文件。Makefile通常包括以下内容:
- 目标(target):需要生成的文件或执行的操作
- 依赖(prerequisites):生成目标所需的文件
- 命令(recipe):实际执行的命令
示例Makefile片段:
main.o: main.c
gcc -c main.c
make是一个命令行工具,用于解析Makefile并执行其中定义的命令。它根据文件的时间戳判断是否需要重新编译,只编译发生变化的文件,从而提高效率。主要功能包括:
- 自动检测文件变更
- 并行执行任务(通过-j参数)
- 处理复杂的依赖关系
常用命令:
make # 编译默认目标
make clean # 执行clean目标
make -j4 # 使用4个线程并行编译
qmake是Qt提供的构建工具,专门用于Qt项目的配置和编译。它生成适合不同平台的Makefile,简化跨平台开发。主要特点包括:
- 解析.pro项目文件
- 自动处理Qt特有的元对象编译器(moc)等流程
- 生成平台特定的Makefile
示例.pro文件:
QT += core gui
TARGET = MyApp
SOURCES += main.cpp
三者关系:qmake生成Makefile,make解析执行Makefile中的指令。在Qt项目中,通常使用qmake创建Makefile,再通过make进行实际编译。这种分工使得跨平台开发更加便捷,同时保留了make的高效构建能力。
构建和运行
添加编译命令
测试编译命令
- main.cpp
#include "widget.h"
#include <QApplication> // 包含一个应用程序类的头文件
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv); // 应用程序对象,在Qt中,有且仅有一个
Widget w; // 窗口对象,Widget父类 -> QWidget
w.show(); // 窗口对象,默认不会显示,必须调用show方法
qDebug() << argc; // 输出命令行的参数数量
for(int i=0; i<argc; i++) { // 输出命令行的参数
qDebug() << argv[i];
}
return a.exec(); // 让应用程序对象进入消息循环,应用程序就阻塞在这里
}
新增按钮 QPushButton

- widget.cpp
#include "widget.h"
#include <QPushButton>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QPushButton *btn1 = new QPushButton(this);
btn1->setText("按钮1"); // 按钮的位置默认 (x,y) = (0,0)
QPushButton *btn2 = new QPushButton("按钮2", this);
btn2->move(100, 200); // 设置按钮的位置 (x,y) = (100,200)
}
Widget::~Widget() {}
信号与槽
信号与槽(Signals and Slots)是一种用于对象间通信的机制,广泛应用于Qt框架中。其核心思想是解耦发送者和接收者,通过信号(事件触发)和槽(事件处理函数)的绑定实现灵活的对象交互。
信号是对象在特定事件发生时发出的通知,例如按钮点击(clicked)。槽是普通的成员函数,用于响应信号并执行逻辑。信号与槽通过connect函数建立关联,当信号被触发时,自动调用连接的槽函数。
信号与槽的特点
- 松耦合:发送者无需知道接收者的具体实现,仅需关注信号与槽的接口。
- 类型安全:信号和槽的参数类型必须匹配,否则编译时会报错(Qt5及以上版本支持编译期检查)。
- 多对多关系:一个信号可以连接多个槽,一个槽也可以响应多个信号。
信号与槽的连接方式
- 字符串方式 SIGNAL / SLOT(Qt4):
connect(sender, SIGNAL(signalName(parameters)), receiver, SLOT(slotName(parameters)));
- 函数地址方式(Qt5):
connect(sender, &SenderClass::signalName, receiver, &ReceiverClass::slotName);
- Lambda表达式:
可直接在connect中编写逻辑:
connect(button, &QPushButton::clicked, this, []() {
qDebug() << "Lambda slot called";
});
-
UI设计师界面-转到槽
-
UI设计师界面-信号槽编辑器
注意事项
- 使用信号与槽的类必须包含
Q_OBJECT宏。 - 避免在槽函数中执行耗时操作,以免阻塞事件循环。
- 断开连接使用
disconnect,防止重复触发或内存泄漏。
信号与槽机制是Qt的核心特性之一,极大简化了事件驱动编程的复杂度。
帮助文档

点击进入父类,查看信号与槽函数。

定义按钮,使用信号与槽

- widget.cpp
#include "widget.h"
#include <QPushButton>
Widget::Widget(QWidget *parent) : QWidget(parent)
{
resize(200, 300); // 设置窗体大小
QPushButton *btn1 = new QPushButton(this);
btn1->setText("按钮1"); // 按钮的位置默认 (x,y) = (0,0)
// 1. Qt5 信号与槽建立方式
// 调用系统槽函数 showFullScreen,全屏
// 哈哈,你上当了吧,知道怎么退出全屏吗?试试 win+D
connect(btn1, &QPushButton::clicked, this, &Widget::showFullScreen); // 库里的槽函数
connect(btn1, &QPushButton::clicked, this, &Widget::btn1_show);
QPushButton *btn2 = new QPushButton("按钮2", this);
btn2->move(0, 50);
// 2. Qt4 信号与槽建立方式
connect(btn2, SIGNAL(clicked(bool)), this, SLOT(showMaximized())); // 库里的槽函数
connect(btn2, SIGNAL(clicked(bool)), this, SLOT(btn2_show()));
QPushButton *btn3 = new QPushButton("按钮3", this);
btn3->move(0, 100);
// 3. 利用Lambda表达式实现槽函数
connect(btn3, &QPushButton::clicked, this, [&](){ showMessage("btn3"); });
}
void Widget::btn1_show() { qDebug() << "btn1"; }
void Widget::btn2_show() { qDebug() << "btn2"; }
void Widget::showMessage(QString str) { qDebug() << str; }
Widget::~Widget() {}

- widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QDebug>
#include <QString>
class Widget : public QWidget
{
Q_OBJECT // Q_OBJECT宏,允许类中使用信号和槽机制
public:
Widget(QWidget *parent = nullptr); // 构造函数
~Widget(); // 析构函数
public slots: // 槽函数
void btn1_show();
void btn2_show();
void showMessage(QString str);
};
#endif // WIDGET_H
Qt 快捷键
| 快捷键 | 作用 |
|---|---|
| Ctrl + / | 注释/取消注释当前行 |
| Ctrl + B | 构建项目 |
| Ctrl + R | 运行当前项目 |
| Ctrl + L | 在编辑模式和设计模式间切换 |
| Ctrl + K | 定位到文件或符号 |
| Ctrl + Tab | 切换打开的文件标签 |
| Ctrl + Shift + up / down | 上移 /下移当前行代码 |
| Ctrl + Alt + up/ down | 向上 / 下复制当前行代码 |
| Ctrl + Shift + R | 全局替换 |
| Alt + left / right | 在历史导航位置间切换 |
| F2 | 跳转到符号定义 |
| F3 | 进入设计模式(Qt Designer) |
| F5 | 开始调试 |
| F10 | 单步跳过 |
| F11 | 单步进入 |
| 自定义快捷键 | 通过 Tools > Options > Environment > Keyboard 可修改或添加快捷键。支持按功能搜索并绑定新组合键。部分快捷键在 macOS 上需替换 Ctrl 为 Command 键,例如 Command + B 构建项目。Linux 与 Windows 快捷键基本一致。 |
自定义信号与槽
新建 Sender 类作为信号发送者

- sender.h
#ifndef SENDER_H
#define SENDER_H
#include <QObject>
// 1. 继承自 QObject
class Sender : public QObject
{
// 2. 添加 Q_OBJECT 宏,才能支持信号槽机制
Q_OBJECT
public:
explicit Sender(QObject *parent = nullptr);
// 3. 在signals下添加自定义信号,信号只需声明,无需实现,返回值为 void
signals:
void click();
};
#endif // SENDER_H
- sender.cpp
#include "sender.h"
Sender::Sender(QObject *parent)
: QObject{parent}
{}
新建 Receiver 类作为信号接收者
- receiver.h
#ifndef RECEIVER_H
#define RECEIVER_H
#include <QObject>
#include <QDebug>
class Receiver : public QObject
{
Q_OBJECT
public:
explicit Receiver(QObject *parent = nullptr);
signals:
// 槽函数的返回值和参数,要和信号保持一致
public slots:
void execute(); // Alt + Enter 快速生成函数定义
};
#endif // RECEIVER_H
- receiver.cpp
#include "receiver.h"
Receiver::Receiver(QObject *parent)
: QObject{parent}
{}
void Receiver::execute()
{
qDebug() << "execute";
}

- main.cpp
#include "widget.h"
#include <QApplication> // 包含一个应用程序类的头文件
#include <QDebug>
#include <sender.h>
#include <receiver.h>
int main(int argc, char *argv[])
{
QApplication a(argc, argv); // 应用程序对象,在Qt中,有且仅有一个
Widget w; // 窗口对象,Widget父类 -> QWidget
w.show(); // 窗口对象,默认不会显示,必须调用show方法
qDebug() << argc; // 输出命令行的参数数量
for(int i=0; i<argc; i++) { // 输出命令行的参数
qDebug() << argv[i];
}
// 1. 创建发送者、接收者对象
Sender sender;
Receiver receiver;
// 2. 建立信号与槽的链接
QObject::connect(&sender, SIGNAL(click()), &receiver, SLOT(execute()));
// 3. 发送信号 emit 可省略
/*emit*/ sender.click();
return a.exec(); // 让应用程序对象进入消息循环,应用程序就阻塞在这里
}
信号与槽函数重载
在信号与槽中添加重载函数
sender.h 文件
signals:
void click();
void click(QString); // 重载
---------------------------------------------------
receiver.h 文件
public slots:
void execute(); // Alt + Enter 快速生成函数定义
void execute(QString);
---------------------------------------------------
receiver.cpp 文件
void Receiver::execute(){
qDebug() << "execute";
}
void Receiver::execute(QString str){
qDebug() << "execute for " << str;
}
---------------------------------------------------
main.cpp 文件
// 1. 创建发送者、接收者对象
Sender sender;
Receiver receiver;
// 2. 建立信号与槽的链接
QObject::connect(&sender, SIGNAL(click()), &receiver, SLOT(execute()));
QObject::connect(&sender, SIGNAL(click(QString)), &receiver, SLOT(execute(QString)));
// 3. 发送信号 emit 可省略
emit sender.click();
emit sender.click("overload");

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)