推荐: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)模式包括 DebugReleaseProfile,它们的主要区别在于编译配置、优化级别和附加工具的启用情况,适用于不同的开发阶段。

  • 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函数建立关联,当信号被触发时,自动调用连接的槽函数。

信号与槽的特点

  1. 松耦合:发送者无需知道接收者的具体实现,仅需关注信号与槽的接口。
  2. 类型安全:信号和槽的参数类型必须匹配,否则编译时会报错(Qt5及以上版本支持编译期检查)。
  3. 多对多关系:一个信号可以连接多个槽,一个槽也可以响应多个信号。

信号与槽的连接方式

  • 字符串方式 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");

在这里插入图片描述

Logo

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

更多推荐