1. Hello Qt¶
本章我们开始学习Qt Creator、工程文件的创建、以及构建运行等操作。
Qt是一个C++应用程序框架,首先我们需要掌握C++的知识,其次才是熟悉Qt的相关特性,这里就默认读者已经对C++有所了解。 这章将以简单的Hello qt例程介绍下项目的文件组成和管理、项目的构建、与运行,以及在鲁班猫板卡上部署。
提示
Qt开发环境:如果是交叉编译,Qt源码版本是5.15.8/6.2.4;如果是在板卡上编译,根据系统不同Qt版本不同。
1.1. 创建一个简单工程¶
我们依然从最基础的Hello Qt开始,使用Qt Creator创建一个简单工程。
打开Qt Creator,点击 创建项目
,选择 Qt Widgets Application
:
重命名工程,设置路径,新建一个空白工程:
选择用什么构建项目:
接下来设置要创建的类名、选择其父类(默认选择了QMainWindow)、编辑相关的头文件和源码文件名,勾选form复选框来创建ui文件(这些可以根据自己工程修改,教程是都保持默认值):
然后选择构建套件:
最后点击完成工程的构建,工程界面显示:
创建完成,最终会切换到这个界面,
编号1为工程的项目结构,也可以切换到其他视图;
编号2为代码编辑区域;
编号3则是编译生成的Qt程序预览;
编号4选择不同的kits来编译不同平台的Qt程序;
编号5为编译构建项目并运行。
切换到我们创建指定的工程目录,该目录下会有项目结构中显示的文件:
一些工程文件的解释:
.h .c++ 文件为头文件和源文件,我们的代码通常都是写在这两种文件中的
.ui 文件就是我们前面提到界面文件,其实质是xml格式的文本文件
.pro 文件就是工程管理文件,以qmake特有的语法记录了工程的文件和配置
.pri pri文件通常也用于工程管理,将代码整理成一个模块,通过引入pri文件来引入代码模块
.pro.user 为用户描述文件,记录了我们工程的开发环境构建环境等等,也是xml格式的文本文件
.qrc 除上面的文件,工程中一般还会有qrc资源文件,用于记录图片,音视频等文件
提示
更多.pro工程文件的配置项详细,或者想了解工程的配置,查看下https://doc.qt.io/qt-6/qmake-project-files.html
我们双击工程管理里面的mainwindow.ui,会切换到可视化的UI设计窗口QtDesigner。
编号1为Qt给我们提供的标准控件,可以拖控件到编号为3的区域。
编号2为布局和界面设计工具栏,前面几个是进入不同的设计模式,后面是界面的布局
编号3选中区域为窗口布局区域,待设计的界面为窗体(form),运行起来的界面就是窗口。图片中我们添加了一个控件,显示”Hello Qt”。
编号4为信号与槽编辑器与 Action 编辑器,进行可视化地进行信号与槽的关联,可视化设计 Action。
编号5为对象浏览栏,用树状视图显示窗体上各组件之间的布局包含关系。
编号6为属性编辑器,属性编辑器显示某个选中的组件或窗体的各种属性及其取值,可以在属性编辑器里修改这些属性的值。
关于Qt Designer更多描述参考下 野火Qt教程 以及Qt官网的 Qt Designer教程 。
点击左侧编辑,回到代码编辑界面。 这时我们会看到,代码编辑区域出现大篇幅字符,这时XMl格式的文本。 其文本内容记录着我们刚刚编辑的UI信息,比如窗口,Label显示的位置、内容等等。 当我们拖动控件,调整UI的时候,QtDesigner会自动更新XML文本。
点击左侧的小电脑配置程序,选择前面选择的kits套件,选择 Desktop Qt5.15.2 GCC 64-bit Debug 套件, 然后点击绿色三角形符号,编译运行程序就会看到:程序主界面上多出了 ‘Hello Qt’ 的字样。
1.2. Hello widget¶
上面使用Qt可视化工具创建了一个hello qt窗口,下面演示使用代码来创建一个widget窗口。
首先点击工程目录,鼠标右键单击,然后点击 Add New … 新建文件,选择C++中的类,点击choose:
修改类名,MyWidget,包含QObject和QWidget:
直接点击完成:
最终在工程以及工程目录下都添加了mywidget.h和mywidget.cpp:
在这两个文件中,手动修改代码,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #ifndef MYWidget_H
#define MYWidget_H
#include <QWidget>
#include <QObject>
class MyWidget : public QWidget
{
Q_OBJECT
public:
explicit MyWidget(QWidget *parent = nullptr);
signals:
public slots:
};
#endif // MYWidget_H
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #include "mywidget.h"
#include <QLabel>
#include <QBoxLayout>
MyWidget::MyWidget(QWidget *parent) : QWidget(parent)
{
// 创建一个 QLabel 控件,并设置文本为 "hello widget"
QLabel *label =new QLabel("hello widget");
// 设置 QLabel 对齐方式为居中对齐
label->setAlignment(Qt::AlignCenter);
// 创建一个 QVBoxLayout 布局,并将其设置为 MyWidget 的布局
QVBoxLayout *verLayout = new QVBoxLayout(this);
// 设置布局的边距为0
verLayout->setContentsMargins(0, 0, 0, 0);
// 设置布局的间距为0,以避免控件之间的间隔
verLayout->setSpacing(0);
// 将 QLabel 控件添加到垂直布局中
verLayout->addWidget(label);
}
|
在这两个文件中,我们创建了一个类MyWidget,这个类继承自QWidget,具备QWidget的所有public属性。 在MyWidget类的构造函数中,我们定义了一个QLabel,label中有文字 hello widget, 我们通过 setAlignment 设置label上的文字居中显示。
然后我们又定义了一个垂直布局的类 QVBoxLayout,我们把label添加到布局中, QVBoxLayout会自动根据其父窗口的大小位置,将label以最合适方式进行缩放、调整。
最后,修改main.cpp内容,注释掉之前自动创建的 MainWindow w ,手动定义 MyWidget w 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #include "mainwindow.h"
#include "mywidget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//MainWindow w;
MyWidget w;
w.resize(640, 480);
w.show();
return a.exec();
}
|
在main函数中,我们定义了一个应用程序a和窗口w,我们设置窗口大小 640*480 ,并通过 show 将其显示。 随后a.exec()会让整个应用进入 事件循环。
比如当我们改变窗口大小时,会产生绘图事件,Qt就会将显示的窗口进行重绘; 当我们点击关闭按钮时,就会产生关闭事件,Qt就会结束应用 。
上面的一连串的代码修改最终的效果和使用Qt Designer最终效果相同, 使用Qt Designer显然更加快捷,但是代码方式更加灵活,两者都需要掌握。
1.3. 例程说明¶
文档所涉及的示例代码可以从网盘配套资料获取,也可以从下面仓库获取:
1.3.1. 例程编程思路¶
使用Qt Creator创建一个HelloQt简单工程;
向默认生成的UI添加QLabel,显示 hello qt;
向工程中添加一个窗口类,MyWdiget;
代码添加一个QLabel,显示 hello widget;
主函数声明 MyWdiget w,并显示。
1.3.2. 编译构建¶
这算是第一次讲解Qt程序的构建,会比较详细,后面都是按照这个套路来。
在左下角有四个按钮,其功能分别是,编译配置,编译并运行程序,编译并调试程序,仅编译程序。
先点击左侧的小电脑配置程序,会弹出几个选择框
构建套件,使用 Desktop Qt5.15.2 GCC 64-bit 编译的程序可在Ubuntu上运行程序,为系统自动配置的构建套件;使用 LubanCat-RK 则会生成能在LubanCat上运行的可执行程序。
构建模式:Debug:调试版本,包含调试信息,所以构建好的程序比Release大很多,并且不进行任何优化,便于程序员调试; Release:发布版本,不对源代码进行调试,编译时对应用程序的速度进行优化,使得程序在代码大小和运行速度上都是最优;Profile 则是在这两种之中取一个平衡,兼顾性能和调试
最后一个为要编译的程序,一个工程包含多个子项目时使用。
套件配置完毕就可以开始编译。 选择底部有八个选项用于log输出,选择编译输出, 窗口输出程序编译时候的log,debug模式也可以看debug输出。
除此以为,我们可以直接鼠标右键某个工程进行编译、清除、重新构建。
提示
当两种构建套件进行切换时,请重新构建项目或清除之前项目。
1.3.3. 运行结果¶
1.3.3.1. ubuntu20.04上直接编译运行¶
选择“Desktop Qt5.15.2 GCC 64-bit”构建套件,然后在虚拟机ubuntu20.04上直接点击 绿色三角形符号,编译并运行程序,效果如下:
如果是在板卡上使用Qt Creator,可以直接点击编译运行,不需要下面的操作。
1.3.3.2. 交叉编译部署到板卡¶
选择*LubanCat-RK*构建套件,然后部署到板卡可以使用远程连接部署,或者单独编译,然后将编译好的程序拷贝到LubanCat上。
直接远程连接部署
远程连接部署参考下前面环境 搭建章节
先修改下部署的路径,打开helloqt.pro,修改 target.path = /home/cat/
,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | # 添加QT项目需要的模块
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
# 添加c17配置支持
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 \
mainwindow.cpp \
mywidget.cpp
# 头文件
HEADERS += \
mainwindow.h \
mywidget.h
# UI
FORMS += \
mainwindow.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /home/cat/
!isEmpty(target.path): INSTALLS += target
|
远程连接参考下前面的环境搭建章节,这里点击选择使用*LubanCat-RK* 编译套件:
点击构建运行,会自动部署到板卡,并运行:
板端显示结果(带桌面系统的Debian10):
并把可执行文件传输到/home/cat/目录下:
cat@lubancat:~$ file helloqt
helloqt: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter
/lib/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, with debug_info, not stripped
cat@lubancat:~$
单独编译拷贝到板卡部署:
拷贝可执行程序到板卡,可以通过SCP、NFS、sftp、u盘等。 NFS使用 参考这里
SCP命令如下:
# scp传输文件,ip地址根据具体板子和PC,板子和PC在一个局域网下
# scp 文件名 服务器上的某个用户@服务器ip:/文件保存路径
scp filename server_user_name@192.168.103.102:server_file_path
# 从服务器拉取文件
# scp 服务器上的某个用户@服务器ip:/服务器文件存放路径 拉取文件保存路径
scp server_user_name@192.168.103.102:server_file_path local_path
编译好的程序在 lubancat_qt_tutorial_code 目录中,通过scp命令将编译好的程序拉到LubanCat。
# 可执行程序文件的目录,根据自己实际项目设置的目录
scp root@192.168.103.102:~/lubancat_qt_tutorial_code/xxx/helloqt ~/
在LubanCat板卡上运行程序,执行helloqt。
# 简单设置环境,然后执行程序
cd ~
./helloqt