Qt Creator软件篇
1. Qt Creator简介
1.1. Qt下载
官方地址
说明 | 地址 |
---|---|
QT官方 | https://download.qt.io/archive/ |
文档 | https://doc.qt.io/qt-6/qtcore-index.html |
国内开源软件镜像下载地址:
source | 地址 |
---|---|
清华大学 | https://mirrors.tuna.tsinghua.edu.cn/qt/ |
中国科学技术大学 | http://mirrors.ustc.edu.cn/qtproject/ |
北京理工大学 | http://mirror.bit.edu.cn/qtproject/ |
以官方下载目录为例,各个目录说明参考如下:
name | 版本 | 说明 |
---|---|---|
snapshots | 预览版 | 最新的开发测试中的QT库和开发工具 |
online | 在线版 | QT在线安装源 |
official_releases | 正式发布版 | 与开发版相对的稳定版QT库和开发工具,可下载QT开发环境和源代码 |
new_archive | ||
ministro | 迷你版 | 目前只针对Android版本 |
linguist_releases | ||
learning | 有学习QT的文档教程和示例视频 | |
development_releases | 开发版 | 有新的旧的不稳定版本,在QT开发过程中的非正式版本 |
community_releases | 社区版 | 社区定制的QT库,以及QT附加的源代码 |
archive | 各种QT开发工具安装包,可下载QT开发环境和源代码 | |
timestamp.txt |
2. Qt 安装详解
前言:
之所以要写安装这一部分,是因为突然之间在线版的qt安装包不能安装历史版本,因开发需要又需要某个特定版本的Qt,困扰了终于解开,特此整理出来详细过程,以帮助有类似囧境的童鞋。
以在线版为例:
下载地址为:https://download.qt.io/archive/online_installers/4.5/
选择:qt-unified-windows-x64-4.5.1-online.exe
2.1 Qt 安装过程
Qt 在线版安装,安装最新版和历史版本,在第5步和第6步进行区分
- 登录Qt账户,没有的话注册一个。
- 勾选条款,并进行下一步
我已阅读并同意使用开源Qt的条款和条件
我是个人用户,我不为任何公司使用Qt - 勾选Disable……,并进行下一步
- 指定安装Qt目录为:C:\Qt
- 若安装最新版qt,则进行下一步,否则跳转到第6步
- 安装历史版本,以Qt 5.15.2版本为例,勾选Archive,再点击筛选。这里需要等待一段时间。
- 在版本列表中找到Qt 5.15.2
- 选择编辑器库及版本,根据个人需求,这里选择 msvc2019_64和mingw81_64
- 选择开发设计工具
- 选择开发设计工具 Qt Creator。
- 选择了两个Windows系统上的调试器。
- CMake构建工具。
- 勾选许可协议选择界面,点击下一步
- 设置开始菜单快捷方式,点击下一步
- Qt 预安装空间,点击下一步
- 一个漫长的安装过程,等待即可
- 安装完成
2.2 Qt 安装目录
- 目录文件结构
当完成Qt开发环境的安装后,其目录文件结构如下图所示:
DIR | 说明 |
---|---|
5.15.2 | 该目录下放置则是不同的Qt版本。 |
dist | 存放安装器的更改日志。 |
Docs | 存放文档的目录。 |
Example | QtCreator在启动的时候,会加载许多Demo,这些Demo的源码则存放于该目录中。 |
installerResource | 存放安装器的资源配置文件。 |
Licenses | 存放Qt的许可协议。 |
Tools | 该目录用于存放Qt开发环境中的工具。例如:QtCreator、编译器套件等都会放在该目录中。 |
vcredist | 存放Windows平台和Visual Studio相关的环境文件。 |
Qt 版本,C:\Qt\5.15.2
目录
DIR | 说明 |
---|---|
bin | 存放该Qt版本的构建工具。 |
doc | 文档目录。 |
include | 存放头文件。 |
lib | 存放该版本的库文件,在Qt应用编译过程中需要使用到。 |
mkspecs | 平台配置文件。 |
plugins | 存放插件的目录。 |
qml | 存放与qml相关的动态库文件,Qt提供了大量的QML类型,我们自己开发的QML应用都需要该目录下的dll文件支持。 |
tanslations | 翻译文件。 |
Qt Tools,C:\Qt\Tools
目录
附录1 Qt常用的命令(快捷键)
- ctrl + shift + F QT中繁体和简体的切换
- alt + 0 显示/隐藏左边条(项目栏)
- ctrl + E + 2 上下分栏
- ctrl + E + 3 左右分栏
- ctrl + E + 1 删除所有分栏
- ctrl + B 编译工程
- ctrl + R 运行工程
- F5 开始调试(继续调试)
- shift + F5 停止调试
- F9 单步调试
- F10 单步前进
- F11 单步进入函数
- shift + F11 单步跳出函数
- F2 跳到函数定义(ctrl + 左键)
- shift + F2 声明和定义之间切换
- F4 .h和.cpp之间切换
- alt + ← 后退
- alt + → 前进
- alt + Enter 将光标移动到h的方法声明处
- alt + Enter 在cpp中添加该函数的定义
- ctrl + space 自动补全
- ctrl + [ 跳到代码的头部
- ctrl + ] 跳到代码的尾部
- ctrl + F 查找当前选中内容
- ctrl + i 自动对齐
- ctrl + / 注释
- ctrl + shift + R 全局修改
- ctrl + shift + up 当前代码向上一行
- ctrl + shift + down 当前代码向下一行
- ctrl + Alt+ ↑ 当前代码向上复制一行
- ctrl + Alt+ ↑ 当前代码向上复制一行
- ctrl + Insert 复制当前行
- ctrl + d 删除当前行
- shift + alt 竖直选择代码
- shift + delete 剪切当前行,可以当做删除用
附录2 Qt 常见Bug及工程问题 解决方法
QT5发布程序自动拷贝依赖库
- 程序能运行但不能断点调试 或 Coulde not find the Qt platform plugin “windows” in “”
编译程序后,运行程序报以上错误。
- 如工程采用 “MSVC 2019 64-bit” 进行构建和运行
- 开始菜单中找到 **"Qt 5.15.2 (MSVC 2019 64-bit) "**打开
- 输入
windeployqt.exe
+编译后的exe文件路径
Qt 创建的窗口一闪而过
- 将窗口变量写到.h文件, 因为函数内部的(普通)变量存在于栈上,函数执行完就会自动销毁,且show函数又不会阻塞,所以show后函数接着往下执行,函数执行完毕后就会销毁创建的窗口变量。
- 修改为创建指针变量, 直接在函数内部将变量创建为指针在show即可,但是这样会产生内存泄漏;同样推荐在.h文件中创建窗口指针变量,并用智能指针进行管理
- 使用阻塞的exec调用。
设置进程只能打开一个,避免重复打开
在main.cpp文件中加入以下头文件
//头文件
#include <QSharedMemory>
#include <QMessageBox>
在主界面显示之前,创建共享内存块,并进行判断
int main()
{
QApplication a(argc, argv);//必须在这一行下面
//******************************************************************************************//
//创建“SingleApp”的共享内存块
static QSharedMemory *singleApp = new QSharedMemory("SingleApp");
if(!singleApp->create(1))//创建失败,说明已经有一个程序运行,
{
//弹出提示框 注意:该提示应该在 qApp->quit() 之前,否则提示框将会一闪而过
QMessageBox::critical(NULL, QStringLiteral("打开程序失败"), QStringLiteral("程序已经运行,无法重复打开!"));
qApp->quit();//退出当前程序
return -1;
}
//******************************************************************************************//
MainWindow w;
w.show();
return a.exec();
}
绝对路径 和 相对路径
这里首先区分 当前目录 和 当前文件路径 两个概念。
- 当前目录,其绝对路径是指在配置工程时,qro或CMakelists所在的路径为当前工程的当前目录,此时的相对路径是相对于该文件。
- 当前文件路径,其绝对路径是指在写代码时,cpp、c或h文件所在的路径,而相对路径则是相对于exe文件。
获取当前路径代码
qDebug() << QDir::currentPath(); //输出的exe文件所在代码
在使用相对路径时,这里区分"./“、”…/“、”😕"三个概念。
./ :表示当前路径 如“./log/log1.txt” 表示当前路径下的log目录下的log1.txt
../ :表示上一级路径。
:/ :表示对资源的引用,引用资源文件(qrc)路径如“:/image/start.png” 表示qrc里定义的文件start.png
获取时间戳
- C++/linux/QT获取纳秒或微妙时间戳
- 获取纳秒或微妙时间戳的两种方法
//方法一
struct timespec {
time_t tv_sec; /* 秒*/
long tv_nsec; /* 纳秒*/
};
clock_gettime(clockid_t clock_id, struct timespec *tp);
#include <time.h>
struct timespec time = {0, 0};
clock_gettime(CLOCK_MONOTONIC, &time);
long long current_time = (long long) time.tv_sec * 1e6 + time.tv_nsec);
//CLOCK_MONOTONIC:
//CLOCK_PROCESS_CPUTIME_ID:
//CLOCK_THREAD_CPUTIME_ID:
//CLOCK_REALTIME //系统当前时间,从1970年1.1日算起
//CLOCK_MONOTONIC //从系统启动这一刻起开始计时,不受系统时间被用户改变的影响,不能被设置;
//CLOCK_PROCESS_CPUTIME_ID //本进程运行时间,本进程到当前代码系统CPU花费的时间
//CLOCK_THREAD_CPUTIME_ID //本线程运行时间,本线程到当前代码系统CPU花费的时间
//方法二
struct timeval {
long tv_sec; /* 秒 */
long tv_usec;/* 微秒 */
};
#include <sys/time.h>
timeval time;
gettimeofday(&time, nullptr);
long long current_time = (long long) time.tv_sec * 1e6 + time.tv_nsec);
- clock_gettime() 与 gettimeofday() 的区别
- 精度区别
clock_gettime() 精确到纳秒,gettimeofday()精确到微秒; - 获取方式不同
clock_gettime()可通过clock_id(时钟)获得不同参考下的时间,而gettimeofday() 只能获取当前系统的时间;
Qt中文乱码问题
Qt分辨率问题
2. QT页面小技巧
2.1 mainwindow
- menubar菜单栏
.h文件
QMenu* menu_help;
QAction* action_abort ; //menu-action
void HelpActions();
.cpp
menu_help = new QMenu(QStringLiteral("帮助(H)"));
action_abort = new QAction(QStringLiteral("关于"));
menu_help->addAction(action_abort);
ui->menubar->addMenu(menu_help);
connect(action_abort , &QAction::triggered, this, &MainWindow::HelpActions);
槽函数
void mainwindow::HelpActions()
{
}
2.2 Qt窗体间传递变量
UI_A 向 UI_B 发送数据
1. Signal&Slot机制进行传值
在UI_A的 .h 文件中定义信号
signals:
void sendData(QString);
在UI_B的 .h 中定义槽函数
private slots:
void receiveData(QString data);
在UI_B
//信号槽方式下父子窗体传值的测试
UI_A* A = new UI_A;
//关联信号和槽函数
connect(A,SIGNAL(sendData(QString)),this,SLOT(receiveData(QString)));
// dlg->setModal(true); 不论是模态或者非模态都可以正常传值
A->show();
UI_A 向 UI_B 发送数据时,只需要在 .cpp 文件中
emit sendData("hello world");
2. 使用全局变量
QString globaldata; //声明一个全局变量用于窗体间传值
在UI_A中声明外部变量
extern QString globaldata;
在UI_A中声明外部变量
globaldata = "hello world";
这种方式,可以看到一些缺点,就是不容易对UI界面进行实时显示,但是这对于一个系统来讲也有一些优势,就是可以方便地将一个系统的配置分配到相关的UI界面中去,但是,同样的,也增加了程序之间的耦合性。
3. 使用接口的形式
在UI_A 定义public接口
public:
void GetData(QString& str);
void SetData(const QString& str);
3. 多线程
thread的调用方式
参数 | 说明 |
---|---|
detach | 启动的线程自主在后台运行,当前的代码继续主下执行,不等待新线程结束。 |
join | 等待启动的线程完成,才会继续往下执行。 |
connect第五个参数
参数 | 说明 |
---|---|
Qt::AutoConnection | 默认值,使用这个值则连接类型会在信号发送时决定。如果接收者和发送者在同一个线程,则自动使用Qt::DirectConnection类型。如果接收者和发送者不在一个线程,则自动使用Qt::QueuedConnection类型。 |
Qt::DirectConnection | 槽函数会在信号发送的时候直接被调用,槽函数运行于信号发送者所在线程。效果看上去就像是直接在信号发送位置调用了槽函数。这个在多线程环境下比较危险,可能会造成奔溃。 |
Qt::QueuedConnection | 槽函数在控制回到接收者所在线程的事件循环时被调用,槽函数运行于信号接收者所在线程。发送信号之后,槽函数不会立刻被调用,等到接收者的当前函数执行完,进入事件循不之后,槽函数才会被调用。多线程环境下一般用这个。 |
Qt::BlockingQueuedConnection | 槽函数的调用时机与Qt::QueuedConnection一致,不过发送完信号后发送者所在线程会阻塞,直到槽函数运行完。接收者和发送者绝对不能在一个线程,否则程序会死锁。在多线程间需要同步的场合可能需要这个。 |
Qt::UniqueConnection | 这个flag可以通过按位或(1)与以上四个结合在一起使用。当这个flag设置时,当某个信号和槽已经连接爱时,再进行重复的连接就会失败。也就是避免了重复连接。 |
断开连接的方法 | 该方法虽然不是必须使用的,因为当一个对象delete之后,Qt自动取消所有连接到这个对象上面的槽。disconnect(sender,SIGNAL(signal),receiver,SLOT(slot), Qt::DirectConnection); |