目录
[Qt 项目中的 .pro 文件详解](#Qt 项目中的 .pro 文件详解)
[一、.pro 文件的作用](#一、.pro 文件的作用)
[1.1 基本定义](#1.1 基本定义)
[1.2 主要作用](#1.2 主要作用)
[二、.pro 文件的基本结构](#二、.pro 文件的基本结构)
[2.1 基本组成部分](#2.1 基本组成部分)
[3.1 项目基本信息](#3.1 项目基本信息)
[3.2 Qt 模块配置](#3.2 Qt 模块配置)
[3.3 源文件和头文件管理](#3.3 源文件和头文件管理)
[3.4 编译和链接配置](#3.4 编译和链接配置)
[3.5 平台特定配置](#3.5 平台特定配置)
[4.1 条件编译](#4.1 条件编译)
[4.2 文件操作和路径处理](#4.2 文件操作和路径处理)
[4.3 自定义构建步骤](#4.3 自定义构建步骤)
[4.4 子项目配置](#4.4 子项目配置)
[5.1 简单的 GUI 应用程序](#5.1 简单的 GUI 应用程序)
[5.2 复杂的多模块项目](#5.2 复杂的多模块项目)
[5.3 库项目配置](#5.3 库项目配置)
[6.1 路径问题](#6.1 路径问题)
[6.2 模块依赖](#6.2 模块依赖)
[6.3 平台兼容性](#6.3 平台兼容性)
[main(int argc, char *argv[]) 函数参数深度解析](#main(int argc, char *argv[]) 函数参数深度解析)
[1.1 函数签名](#1.1 函数签名)
[1.2 参数含义](#1.2 参数含义)
[2.1 argc - 参数计数器](#2.1 argc - 参数计数器)
[2.2 argv - 参数字符串数组](#2.2 argv - 参数字符串数组)
[3.1 QApplication初始化](#3.1 QApplication初始化)
[3.2 Qt处理的常见命令行参数](#3.2 Qt处理的常见命令行参数)
[4.1 基础示例:打印所有参数](#4.1 基础示例:打印所有参数)
[4.2 Qt应用中的参数处理](#4.2 Qt应用中的参数处理)
[5.1 内存布局详解](#5.1 内存布局详解)
[5.2 参数的生命周期](#5.2 参数的生命周期)
[6.1 文件关联打开](#6.1 文件关联打开)
[6.2 配置应用程序行为](#6.2 配置应用程序行为)
[7.1 Windows vs Unix/Linux](#7.1 Windows vs Unix/Linux)
[7.2 Unicode支持](#7.2 Unicode支持)
[8.1 使用标准库容器](#8.1 使用标准库容器)
[8.2 使用Qt容器](#8.2 使用Qt容器)
[9.1 为什么需要这两个参数](#9.1 为什么需要这两个参数)
[9.2 在Qt中的特殊意义](#9.2 在Qt中的特殊意义)
[9.3 最佳实践](#9.3 最佳实践)
[一、QApplication 类详解](#一、QApplication 类详解)
[1.1 QApplication 的作用](#1.1 QApplication 的作用)
[1.2 QApplication 最常用函数](#1.2 QApplication 最常用函数)
[1.2.1 应用程序信息设置](#1.2.1 应用程序信息设置)
[1.2.2 样式和外观](#1.2.2 样式和外观)
[1.2.3 事件处理](#1.2.3 事件处理)
[1.2.5 系统集成](#1.2.5 系统集成)
[1.3 QApplication 完整示例](#1.3 QApplication 完整示例)
[二、MainWindow 类详解](#二、MainWindow 类详解)
[2.1 MainWindow 的作用](#2.1 MainWindow 的作用)
[2.2 MainWindow 最常用函数](#2.2 MainWindow 最常用函数)
[2.2.1 窗口基本设置](#2.2.1 窗口基本设置)
[2.2.2 中心部件管理](#2.2.2 中心部件管理)
[2.2.3 菜单栏操作](#2.2.3 菜单栏操作)
[2.2.4 工具栏操作](#2.2.4 工具栏操作)
[2.2.6 停靠窗口](#2.2.6 停靠窗口)
[2.3 MainWindow 完整示例](#2.3 MainWindow 完整示例)
[1.1 基本概念再理解](#1.1 基本概念再理解)
[二、 connect 函数连接信号与槽](#二、 connect 函数连接信号与槽)
[1 connect 函数基本语法](#1 connect 函数基本语法)
[2 编译时处理](#2 编译时处理)
[3 运行时处理](#3 运行时处理)
一个简单qt程序的文件构成
.pro文件,Headers 头文件,Sources 源文件,Forms(UI文件)。
-
.pro文件:这是Qt项目的项目文件,类似于其他IDE中的项目配置文件(如Visual Studio的.vcxproj文件)。它告诉qmake如何构建这个项目。其中包含了项目所需的所有源文件、头文件、库、配置等。
-
Headers(头文件):在C++中,头文件通常包含类的声明、函数原型、宏定义等。在Qt中,头文件除了这些,还包含了Qt特有的关键字,比如signals、slots、Q_OBJECT等。这些头文件会被moc(元对象编译器)处理,以支持Qt的信号槽和元对象系统。
-
Sources(源文件):源文件包含类的实现、函数定义等。在Qt中,源文件会包含头文件,并实现其中声明的类。同时,源文件中也可以包含信号和槽的实现。
-
Forms(UI文件):这是Qt Designer创建的界面文件,以.ui为扩展名。这些文件是XML格式的,描述了界面的布局和组件。在构建项目时,uic(用户界面编译器)会将.ui文件转换为相应的C++头文件,这些头文件中包含了界面的类定义。
Qt 项目中的 .pro 文件详解
一、.pro 文件的作用
1.1 基本定义
.pro 文件是 Qt 项目文件 (Qt Project File),它是 qmake 构建系统的配置文件,我们可以将该文件转为cmake文件,可以应用在跟多平台。
1.2 主要作用
-
项目配置:定义项目类型、名称、版本等元数据
-
依赖管理:指定项目依赖的 Qt 模块和第三方库
-
文件组织:列出项目中包含的源文件、头文件、资源文件
-
构建配置:设置编译器选项、链接器选项、平台特定配置
-
部署设置:配置应用程序的安装和部署规则
二、.pro 文件的基本结构
2.1 基本组成部分
pro
bash
# 注释以 # 开头
# 1. 变量赋值
VARIABLE = value
# 2. 变量追加
VARIABLE += new_value
# 3. 变量移除
VARIABLE -= value_to_remove
# 4. 条件判断
condition {
# 条件成立时的配置
} else {
# 条件不成立时的配置
}
三、常用配置写法详解
3.1 项目基本信息
bash
# 项目模板类型
TEMPLATE = app # 应用程序
# TEMPLATE = lib # 库文件
# TEMPLATE = subdirs # 多目录项目
# 目标文件名(生成的可执行文件名称)
TARGET = MyApplication
# 应用程序版本
VERSION = 1.0.0
# 编译目录
DESTDIR = $$PWD/build
3.2 Qt 模块配置
bash
# 核心模块(默认包含,无需显式声明)
QT = core
# 添加其他 Qt 模块
QT += widgets # GUI 组件
QT += network # 网络功能
QT += sql # 数据库支持
QT += multimedia # 多媒体功能
QT += charts # 图表功能
QT += webenginewidgets # Web 引擎
# 配置选项
CONFIG += c++11 # 启用 C++11 标准
CONFIG += console # 控制台应用程序(显示命令行窗口)
CONFIG -= app_bundle # macOS:不创建应用程序包
3.3 源文件和头文件管理
bash
# 源文件列表
SOURCES += \
main.cpp \
mainwindow.cpp \
calculator.cpp \
utils.cpp
# 头文件列表
HEADERS += \
mainwindow.h \
calculator.h \
utils.h
# 界面文件(.ui 文件)
FORMS += \
mainwindow.ui \
settingsdialog.ui
# 资源文件(.qrc 文件)
RESOURCES += \
images.qrc \
translations.qrc
# 翻译文件
TRANSLATIONS += \
myapp_zh_CN.ts \
myapp_en_US.ts
3.4 编译和链接配置
bash
# 包含路径
INCLUDEPATH += \
$$PWD/include \
$$PWD/thirdparty
# 库文件路径
LIBS += -L$$PWD/lib
# 链接库
LIBS += -lmylibrary
LIBS += -lssl -lcrypto
# 或者使用相对路径
LIBS += -L$$OUT_PWD/../mylib -lmylib
# 预处理器定义
DEFINES += DEBUG_MODE
DEFINES += "VERSION=\\\"$$VERSION\\\""
# 编译器标志
QMAKE_CXXFLAGS += -Wall -Wextra -O2
QMAKE_LFLAGS += -static
3.5 平台特定配置
bash
# Windows 平台配置
win32 {
# Windows 特定配置
LIBS += -luser32 -lgdi32
RC_FILE = myapp.rc # 资源文件
}
# Linux 平台配置
unix:!macx {
# Linux 特定配置
LIBS += -lX11 -lXext
QMAKE_CXXFLAGS += -fPIC
}
# macOS 平台配置
macx {
# macOS 特定配置
ICON = myapp.icns
QMAKE_INFO_PLIST = Info.plist
}
# 移动平台
android {
# Android 配置
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
}
ios {
# iOS 配置
QMAKE_IOS_DEPLOYMENT_TARGET = 12.0
}
四、高级配置技巧
4.1 条件编译
bash
# 根据配置选项进行条件编译
CONFIG(release, debug|release) {
# 发布模式配置
DEFINES += NDEBUG
QMAKE_CXXFLAGS += -O2
} else {
# 调试模式配置
DEFINES += DEBUG
QMAKE_CXXFLAGS += -g -O0
}
# 自定义配置选项
CONFIG += my_feature
# 根据自定义选项配置
my_feature {
DEFINES += ENABLE_MY_FEATURE
SOURCES += myfeature.cpp
HEADERS += myfeature.h
}
4.2 文件操作和路径处理
bash
# 自动包含目录下所有文件
SOURCES += $$files(*.cpp, true)
HEADERS += $$files(*.h, true)
# 排除特定文件
SOURCES -= main_test.cpp
# 路径变量
ROOT_DIR = $$PWD
SRC_DIR = $$PWD/src
INCLUDE_DIR = $$PWD/include
# 相对路径处理
INCLUDEPATH += $$relative_path($$PWD, $$SRC_DIR)
4.3 自定义构建步骤
bash
# 在构建前执行的命令
prebuild.commands += echo "开始构建..."
prebuild.depends = $$first(QMAKE_INTERNAL_INCLUDED_FILES)
# 在构建后执行的命令
postbuild.commands += echo "构建完成!"
postbuild.commands += cp $$TARGET $$DESTDIR/
# 添加自定义目标
custom.target = custom_output
custom.commands = python $$PWD/scripts/generate_resources.py
custom.depends = $$SOURCES
QMAKE_EXTRA_TARGETS += prebuild postbuild custom
4.4 子项目配置
bash
# 多目录项目
TEMPLATE = subdirs
SUBDIRS += \
app \
libs/core \
libs/gui
# 子项目的配置传递
app.depends = libs/core libs/gui
五、实际项目示例
5.1 简单的 GUI 应用程序
bash
# 简单的计算器应用
QT += widgets
TARGET = Calculator
TEMPLATE = app
# 启用 C++17
CONFIG += c++17
# 源文件
SOURCES += \
src/main.cpp \
src/mainwindow.cpp \
src/calculator.cpp
HEADERS += \
include/mainwindow.h \
include/calculator.h
# 资源文件
RESOURCES += resources.qrc
# 包含路径
INCLUDEPATH += include
# 平台特定配置
win32 {
# Windows 下使用静态链接减小体积
CONFIG += static
RC_ICONS = icons/app.ico
}
unix {
# Linux 下使用系统托盘
DEFINES += LINUX_TRAY
}
5.2 复杂的多模块项目
bash
# 企业级应用
TEMPLATE = subdirs
SUBDIRS = \
core \
gui \
tests
# 配置选项
CONFIG += ordered # 按顺序构建子项目
# 全局定义
DEFINES += COMPANY_NAME=\"MyCompany\"
VERSION = 2.1.0
# 每个子项目的配置
core.file = core/core.pro
core.depends =
gui.file = gui/gui.pro
gui.depends = core
tests.file = tests/tests.pro
tests.depends = core gui
5.3 库项目配置
bash
# 静态库项目
TEMPLATE = lib
CONFIG += staticlib
TARGET = mylibrary
QT += core
# 库版本
VERSION = 1.2.3
# 安装配置
headers.files = $$HEADERS
headers.path = $$[QT_INSTALL_HEADERS]/mylibrary
target.path = $$[QT_INSTALL_LIBS]
INSTALLS += headers target
六、常见问题解决
6.1 路径问题
bash
# 正确的路径写法
INCLUDEPATH += $$PWD/../thirdparty/include
LIBS += -L$$PWD/../thirdparty/lib
# 避免硬编码路径
THIRDPARTY_DIR = $$PWD/../thirdparty
INCLUDEPATH += $$THIRDPARTY_DIR/include
LIBS += -L$$THIRDPARTY_DIR/lib
6.2 模块依赖
bash
# 正确的模块依赖顺序
QT += core gui widgets # core 应该在前面
# 避免循环依赖
# 如果 A 依赖 B,B 不应该再依赖 A
6.3 平台兼容性
bash
# 跨平台文件路径处理
win32 {
# Windows 使用反斜杠
DEPLOY_PATH = C:/Program Files/MyApp
} else {
# Unix 使用正斜杠
DEPLOY_PATH = /usr/local/myapp
}
# 或者使用 Qt 的路径分隔符
DEPLOY_PATH = $$system_path($$PWD/../deploy)
七、总结
.pro 文件是 Qt 项目的核心配置文件,它:
-
简化构建过程:通过声明式配置自动生成复杂的 Makefile
-
提高跨平台性:通过平台条件判断实现一套代码多平台编译
-
管理项目依赖:清晰定义项目所需的所有资源和库
-
支持灵活配置:通过变量和条件判断支持多种构建场景
掌握 .pro 文件的编写技巧,可以大大提高 Qt 项目的开发效率和质量。在实际开发中,建议根据项目复杂度选择合适的配置方式,并保持配置文件的清晰和可维护性。
main(int argc, char *argv[]) 函数参数深度解析
一、基本概念
1.1 函数签名
cpp
int main(int argc, char *argv[])
这是C/C++程序的标准入口点,参数用于接收命令行输入。
1.2 参数含义
-
argc(argument count):命令行参数的数量 -
argv(argument vector):命令行参数字符串数组
二、参数详细解析
2.1 argc - 参数计数器
cpp
int argc // 整数类型,表示参数个数
特点:
-
至少为1(程序名称本身算作第一个参数)
-
包含所有通过命令行传递的参数数量
2.2 argv - 参数字符串数组
cpp
char *argv[] // 字符指针数组,每个元素指向一个参数字符串
内存布局:
text
argv[0] → "./program"
argv[1] → "arg1"
argv[2] → "arg2"
...
argv[argc-1] → 最后一个参数
argv[argc] → NULL (空指针,标记数组结束)
三、在Qt中的特殊作用
3.1 QApplication初始化
cpp
#include <QApplication>
int main(int argc, char *argv[])
{
// QApplication使用这些参数进行初始化
QApplication app(argc, argv);
// Qt会解析这些命令行参数,处理如:
// -style=windows 设置界面风格
// -font="Arial" 设置字体
// -qws 嵌入式模式
// 等等...
return app.exec();
}
3.2 Qt处理的常见命令行参数
| 参数 | 作用 | 示例 |
|---|---|---|
-style |
设置界面风格 | -style=windows |
-font |
设置字体 | -font="Arial,12" |
-geometry |
设置窗口几何 | -geometry=400x300 |
-display |
设置显示设备 | -display:0 |
-reverse |
反向布局 | -reverse |
四、实际应用示例
4.1 基础示例:打印所有参数
cpp
#include <iostream>
int main(int argc, char *argv[])
{
std::cout << "参数总数: " << argc << std::endl;
for(int i = 0; i < argc; i++) {
std::cout << "参数 " << i << ": " << argv[i] << std::endl;
}
return 0;
}
运行结果:
bash
$ ./program hello world 123
参数总数: 4
参数 0: ./program
参数 1: hello
参数 2: world
参数 3: 123
4.2 Qt应用中的参数处理
bash
#include <QApplication>
#include <QMainWindow>
#include <QLabel>
#include <QVBoxLayout>
#include <QWidget>
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// 在创建窗口前,可以检查特定参数
QString style = "fusion"; // 默认风格
// 检查是否有-style参数
for(int i = 1; i < argc; i++) {
if(QString(argv[i]).startsWith("-style=")) {
style = QString(argv[i]).mid(7); // 提取风格名称
qDebug() << "设置界面风格:" << style;
}
}
// 设置应用程序样式
app.setStyle(style);
// 创建主窗口
QMainWindow window;
QWidget *centralWidget = new QWidget(&window);
QVBoxLayout *layout = new QVBoxLayout(centralWidget);
QLabel *label = new QLabel("命令行参数演示", centralWidget);
layout->addWidget(label);
// 显示所有参数
for(int i = 0; i < argc; i++) {
QLabel *argLabel = new QLabel(QString("参数%1: %2").arg(i).arg(argv[i]), centralWidget);
layout->addWidget(argLabel);
}
window.setCentralWidget(centralWidget);
window.show();
return app.exec();
}
五、参数的内存管理
5.1 内存布局详解
text
命令行: ./myapp -name "John" -age 30
内存中的argv数组:
argv[0] → 地址1 → "./myapp\0"
argv[1] → 地址2 → "-name\0"
argv[2] → 地址3 → "John\0"
argv[3] → 地址4 → "-age\0"
argv[4] → 地址5 → "30\0"
argv[5] → NULL
5.2 参数的生命周期
-
分配:由操作系统在程序启动前分配
-
作用域:在整个main函数执行期间有效
-
释放:程序退出时由操作系统自动回收
六、在图形界面应用中的实际用途
6.1 文件关联打开
bash
#include <QApplication>
#include <QMainWindow>
#include <QLabel>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QMainWindow window;
// 检查是否通过文件关联打开(例如双击文件)
if(argc > 1) {
// argv[1] 可能是要打开的文件路径
QString fileName = argv[1];
QLabel *label = new QLabel(QString("打开文件: %1").arg(fileName));
window.setCentralWidget(label);
} else {
QLabel *label = new QLabel("没有指定文件");
window.setCentralWidget(label);
}
window.show();
return app.exec();
}
6.2 配置应用程序行为
bash
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// 解析命令行配置
bool debugMode = false;
QString configFile = "default.conf";
for(int i = 1; i < argc; i++) {
QString arg = argv[i];
if(arg == "--debug" || arg == "-d") {
debugMode = true;
qDebug() << "调试模式已启用";
}
else if(arg.startsWith("--config=")) {
configFile = arg.mid(9);
qDebug() << "使用配置文件:" << configFile;
}
else if(arg == "--help" || arg == "-h") {
qDebug() << "用法: program [--debug] [--config=file]";
return 0;
}
}
// 根据参数配置应用程序
if(debugMode) {
// 启用调试功能
}
MainWindow window(configFile);
window.show();
return app.exec();
}
七、跨平台注意事项
7.1 Windows vs Unix/Linux
bash
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// 平台特定的参数处理
#ifdef Q_OS_WIN
// Windows特有的参数处理
// 例如处理注册表关联的文件打开
#endif
#ifdef Q_OS_LINUX
// Linux特有的参数处理
// 例如处理X11显示参数
#endif
#ifdef Q_OS_MAC
// macOS特有的参数处理
// 例如处理Bundle相关参数
#endif
return app.exec();
}
7.2 Unicode支持
bash
// 对于需要Unicode支持的Windows程序
#ifdef _WIN32
#include <windows.h>
int wmain(int argc, wchar_t *argv[])
{
// 处理宽字符参数
}
#else
int main(int argc, char *argv[])
{
// 标准参数处理
}
#endif
八、在现代C++中的替代方案
8.1 使用标准库容器
bash
#include <vector>
#include <string>
int main(int argc, char *argv[])
{
// 将C风格数组转换为更安全的std::vector
std::vector<std::string> args(argv, argv + argc);
// 现在可以使用STL算法处理参数
for(const auto& arg : args) {
// 处理每个参数
}
return 0;
}
8.2 使用Qt容器
bash
#include <QApplication>
#include <QStringList>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// 将参数转换为QStringList
QStringList arguments = app.arguments();
// 使用Qt的方式处理参数
for(const QString& arg : arguments) {
qDebug() << "参数:" << arg;
}
return app.exec();
}
九、总结
9.1 为什么需要这两个参数
-
程序灵活性:允许用户通过命令行控制程序行为
-
系统集成:支持文件关联、脚本调用等场景
-
调试和配置:便于测试和不同环境部署
-
标准化:符合POSIX和C/C++标准
9.2 在Qt中的特殊意义
-
框架初始化:QApplication需要这些参数来正确设置环境
-
平台适配:处理不同操作系统的启动差异
-
功能扩展:支持丰富的命令行选项配置应用程序
9.3 最佳实践
bash
int main(int argc, char *argv[])
{
// 1. 总是传递参数给QApplication
QApplication app(argc, argv);
// 2. 尽早处理关键参数(如--help)
if(app.arguments().contains("--help")) {
// 显示帮助信息并退出
return 0;
}
// 3. 使用QApplication::arguments()而不是直接操作argv
QStringList args = app.arguments();
// 4. 设置应用程序属性
app.setApplicationName("我的应用");
app.setApplicationVersion("1.0");
// 创建并显示主窗口
MainWindow window;
window.show();
return app.exec();
}
这两个参数是C/C++程序与操作系统环境交互的重要桥梁,在Qt应用中尤其重要,因为它们为GUI应用程序提供了丰富的配置和集成可能性。
QApplication类与QMainWindow
一、QApplication 类详解
1.1 QApplication 的作用
QApplication 是 Qt 应用程序的核心管理类,负责:
-
管理应用程序的生命周期
-
处理事件循环和事件分发
-
管理系统范围的应用设置
-
处理命令行参数
1.2 QApplication 最常用函数
1.2.1 应用程序信息设置
cpp
// 设置应用程序名称(显示在关于对话框、任务管理器等)
app.setApplicationName("圆面积计算器");
// 设置应用程序版本
app.setApplicationVersion("1.0");
// 设置组织名称(用于注册表、配置文件组织)
app.setOrganizationName("MyCompany");
// 设置组织域名(用于设置文件路径)
app.setOrganizationDomain("mycompany.com");
1.2.2 样式和外观
cpp
// 设置应用程序样式
app.setStyle("Fusion"); // 可选: "Windows", "WindowsVista", "Fusion"
// 设置调色板
QPalette palette;
palette.setColor(QPalette::Window, Qt::white);
app.setPalette(palette);
// 设置字体
QFont font("Arial", 10);
app.setFont(font);
1.2.3 事件处理
cpp
// 获取应用程序目录
QString appDir = app.applicationDirPath();
// 获取应用程序文件路径
QString appFilePath = app.applicationFilePath();
// 获取命令行参数
QStringList args = app.arguments();
// 获取平台名称
QString platform = app.platformName();
1.2.5 系统集成
cpp
// 设置桌面文件(Linux)
app.setDesktopFileName("myapp.desktop");
// 设置窗口图标(所有窗口共享)
app.setWindowIcon(QIcon(":/icons/app_icon.png"));
// 处理会话管理(保存/恢复状态)
app.isSessionRestored(); // 检查是否从会话恢复
1.3 QApplication 完整示例
cpp
#include <QApplication>
#include <QStyleFactory>
#include <QPalette>
#include <QFont>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// 应用程序元数据
app.setApplicationName("高级计算器");
app.setApplicationVersion("2.0.0");
app.setOrganizationName("TechCorp");
app.setOrganizationDomain("techcorp.com");
// 样式设置
app.setStyle(QStyleFactory::create("Fusion"));
// 自定义调色板
QPalette darkPalette;
darkPalette.setColor(QPalette::Window, QColor(53,53,53));
darkPalette.setColor(QPalette::WindowText, Qt::white);
app.setPalette(darkPalette);
// 字体设置
app.setFont(QFont("Microsoft YaHei", 9));
// 窗口图标
app.setWindowIcon(QIcon(":/icons/calculator.png"));
// 显示可用样式
qDebug() << "可用样式:" << QStyleFactory::keys();
MainWindow window;
window.show();
return app.exec();
}
二、MainWindow 类详解
2.1 MainWindow 的作用
MainWindow 是主窗口类,提供:
-
标准的应用程序主窗口框架
-
菜单栏、工具栏、状态栏支持
-
中心窗口部件管理
-
停靠窗口支持
2.2 MainWindow 最常用函数
2.2.1 窗口基本设置
cpp
// 设置窗口标题
setWindowTitle("圆面积计算器");
// 设置窗口图标
setWindowIcon(QIcon(":/icons/window_icon.png"));
// 设置窗口大小
resize(800, 600); // 设置初始大小
setMinimumSize(400, 300); // 设置最小尺寸
setMaximumSize(1200, 800); // 设置最大尺寸
setFixedSize(400, 300); // 固定窗口大小
// 窗口状态
show(); // 显示窗口
showMaximized(); // 最大化显示
showMinimized(); // 最小化显示
showFullScreen(); // 全屏显示
hide(); // 隐藏窗口
close(); // 关闭窗口
2.2.2 中心部件管理
cpp
// 设置中心部件
QWidget *centralWidget = new QWidget(this);
setCentralWidget(centralWidget);
// 获取中心部件
QWidget *currentCentral = centralWidget();
// 设置中心部件为其他类型(如QTextEdit、QGraphicsView等)
QTextEdit *textEdit = new QTextEdit(this);
setCentralWidget(textEdit);
2.2.3 菜单栏操作
cpp
// 创建菜单栏
QMenuBar *menuBar = this->menuBar();
// 添加菜单
QMenu *fileMenu = menuBar->addMenu("文件(&F)");
QMenu *editMenu = menuBar->addMenu("编辑(&E)");
QMenu *helpMenu = menuBar->addMenu("帮助(&H)");
// 添加菜单项
QAction *newAction = fileMenu->addAction("新建(&N)");
QAction *openAction = fileMenu->addAction("打开(&O)");
QAction *exitAction = fileMenu->addAction("退出(&X)");
// 添加分隔符
fileMenu->addSeparator();
2.2.4 工具栏操作
cpp
// 创建工具栏
QToolBar *toolBar = addToolBar("主工具栏");
// 添加工具按钮
toolBar->addAction(newAction);
toolBar->addAction(openAction);
// 添加分隔符
toolBar->addSeparator();
// 添加控件到工具栏
QLineEdit *searchEdit = new QLineEdit();
toolBar->addWidget(searchEdit);
// 设置工具栏属性
toolBar->setMovable(true); // 允许移动
toolBar->setFloatable(true); // 允许浮动
toolBar->setIconSize(QSize(24,24)); // 设置图标大小
2.2.6 停靠窗口
cpp
// 创建停靠窗口
QDockWidget *dockWidget = new QDockWidget("工具面板", this);
// 设置停靠窗口内容
QListWidget *listWidget = new QListWidget();
dockWidget->setWidget(listWidget);
// 添加停靠窗口
addDockWidget(Qt::LeftDockWidgetArea, dockWidget);
// 设置停靠区域允许
dockWidget->setAllowedAreas(
Qt::LeftDockWidgetArea |
Qt::RightDockWidgetArea
);
2.3 MainWindow 完整示例
cpp
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMenuBar>
#include <QToolBar>
#include <QStatusBar>
#include <QDockWidget>
#include <QTextEdit>
#include <QListWidget>
#include <QLabel>
#include <QAction>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
private slots:
void onNewFile();
void onAbout();
void updateStatusBar();
private:
void createMenus();
void createToolBars();
void createStatusBar();
void createDockWindows();
QTextEdit *textEdit;
QAction *newAction;
QAction *aboutAction;
};
#endif // MAINWINDOW_H
cpp
#include "mainwindow.h"
#include <QMenu>
#include <QMessageBox>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
// 窗口基本设置
setWindowTitle("高级文本编辑器");
setWindowIcon(QIcon(":/icons/editor.png"));
resize(1000, 700);
// 创建中心部件
textEdit = new QTextEdit(this);
setCentralWidget(textEdit);
// 创建界面组件
createMenus();
createToolBars();
createStatusBar();
createDockWindows();
// 初始状态栏消息
statusBar()->showMessage("就绪", 2000);
}
void MainWindow::createMenus()
{
// 文件菜单
QMenu *fileMenu = menuBar()->addMenu("文件(&F)");
newAction = new QAction("新建(&N)", this);
newAction->setShortcut(QKeySequence::New);
newAction->setStatusTip("创建新文件");
connect(newAction, &QAction::triggered, this, &MainWindow::onNewFile);
fileMenu->addAction(newAction);
fileMenu->addSeparator();
QAction *exitAction = new QAction("退出(&X)", this);
exitAction->setShortcut(QKeySequence::Quit);
connect(exitAction, &QAction::triggered, this, &QWidget::close);
fileMenu->addAction(exitAction);
// 帮助菜单
QMenu *helpMenu = menuBar()->addMenu("帮助(&H)");
aboutAction = new QAction("关于(&A)", this);
connect(aboutAction, &QAction::triggered, this, &MainWindow::onAbout);
helpMenu->addAction(aboutAction);
}
void MainWindow::createToolBars()
{
QToolBar *mainToolBar = addToolBar("主工具栏");
mainToolBar->addAction(newAction);
mainToolBar->setIconSize(QSize(24, 24));
mainToolBar->setMovable(true);
}
void MainWindow::createStatusBar()
{
statusBar()->showMessage("就绪");
// 永久部件
QLabel *sizeLabel = new QLabel("100%");
statusBar()->addPermanentWidget(sizeLabel);
}
void MainWindow::createDockWindows()
{
QDockWidget *dock = new QDockWidget("文档大纲", this);
QListWidget *listWidget = new QListWidget();
listWidget->addItems(QStringList() << "第一章" << "第二章" << "第三章");
dock->setWidget(listWidget);
addDockWidget(Qt::RightDockWidgetArea, dock);
}
void MainWindow::onNewFile()
{
textEdit->clear();
statusBar()->showMessage("新建文档", 2000);
}
void MainWindow::onAbout()
{
QMessageBox::about(this, "关于",
"高级文本编辑器\n版本 1.0\n版权所有 (C) 2023");
}
void MainWindow::updateStatusBar()
{
statusBar()->showMessage("文档已修改");
}
信号与槽机制
一、信号与槽机制深度解析
1.1 基本概念再理解
信号 (Signal)
cpp
// 信号的本质:特殊的事件通知机制
class QPushButton : public QAbstractButton {
Q_OBJECT
signals:
void clicked(bool checked = false); // 这是一个信号
};
// 信号的特点:
// 1. 只有声明,没有实现(moc自动生成)
// 2. 使用 emit 关键字触发
// 3. 可以被多个槽函数接收
槽 (Slot)
cpp
// 槽的本质:普通成员函数 + 特殊标记
class MainWindow : public QMainWindow {
Q_OBJECT
public slots: // 槽函数标记
void calculateArea(); // 这是一个槽函数
};
// 槽函数的特点:
// 1. 可以是任意访问权限(public/protected/private)
// 2. 需要完整的实现
// 3. 可以像普通函数一样调用
二、 connect 函数连接信号与槽
1 connect 函数基本语法
cpp
connect(
发送者对象指针, // 信号来源
&发送者类::信号名, // 具体的信号
接收者对象指针, // 槽函数所属对象
&接收者类::槽函数名 // 具体的槽函数
);
2 编译时处理
cpp
// 当编译器看到这行代码时:
connect(calculateButton, &QPushButton::clicked, this, &MainWindow::calculateArea);
// 编译器会:
// 1. 检查 calculateButton 是否是 QPushButton* 类型
// 2. 检查 QPushButton 是否有 clicked 信号
// 3. 检查 this 是否是 MainWindow* 类型
// 4. 检查 MainWindow 是否有 calculateArea 槽函数
// 5. 检查信号和槽的参数是否兼容
3 运行时处理
cpp
// 当程序执行 connect 时:
// 1. Qt 在内部创建一个"连接记录"
ConnectionRecord {
发送者: calculateButton,
信号: &QPushButton::clicked,
接收者: this (MainWindow),
槽函数: &MainWindow::calculateArea
}
// 2. 将这个记录存储到全局连接表中
// 3. 当信号发出时,Qt 会查找这个表并调用对应的槽函数