目录
- Qt开发环境QtCreator的安装、配置
- 在QtCreator中创建新工程
- 在`Forms→mainwindow.ui`中拖曳出我们要的图形按钮
- 查看拖曳出按钮后的代码
- 为`pushButton`这个图形添加回调函数
- 编译工程
- 关闭开发板上QT的GUI(选做)
- 禁止LCD黑屏(选做)
- 设置Qt运行的环境变量
- 运行Qt程序
- 如何让程序在系统启动时运行
- 附完整源代码
- mainwindow.ui 中的代码
- mainwindow.h 中的代码
- mainwindow.cpp 中的代码
- main.cpp 中的代码
- 附编译完成后完整的工程目录
Qt开发环境QtCreator的安装、配置
详情见 https://blog.csdn.net/wenhao_ir/article/details/145367198
在QtCreator中创建新工程
然后设置工程的名字和位置:
上图中点击Next…
我们这里使用qmake进行构建,所以选择qmake:
上图中继续点击Next…
这里是设置Qt的C++代码中类的名字和相关文件的名字,这些使用默认的就可以了。
上图中继续点击Next…
上图是设置语言的转换,不是编译语言的转换哈,就是英语、汉语、法语的那种语言,我们不需要作这个操作,所以继续Next。
这里选择在博文 https://blog.csdn.net/wenhao_ir/article/details/145367198 中配置的kit,即 qt_klt_swh_01:
继续Next…
然后Finish…
上面的警告:
Warning: The code model could not parse an included file, which might lead to incorrect code completion and highlighting, for example.
不用管,这个警告是由于下面这句代码出现的:
#include <QApplication>
由于目录:
/home/book/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/arm-buildroot-linux-gnueabihf/sysroot/usr/include/c++
不存在,而导致的。
但我们这里不用管,因为我们后面的代码不会使用头文件#include <QApplication>
在Forms→mainwindow.ui
中拖曳出我们要的图形按钮
双击文件mainwindow.ui
Buttons里拖曳出一个Push Button
【按住下图中的Push Button
不放往中间拖】
按住下图中的Push Button
不放往中间拖:
不妨重命名为LED
左侧图形分类栏往下拉,找到Display Widgets
,然后拖曳出两个Label
查看拖曳出按钮后的代码
点击下图中的Edit
然后就可以看到刚才拖曳出的三个图形对应的源文件(xml语法写成):
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"><class>MainWindow</class><widget class="QMainWindow" name="MainWindow"><property name="geometry"><rect><x>0</x><y>0</y><width>800</width><height>600</height></rect></property><property name="windowTitle"><string>MainWindow</string></property><widget class="QWidget" name="centralwidget"><widget class="QPushButton" name="pushButton"><property name="geometry"><rect><x>90</x><y>130</y><width>89</width><height>25</height></rect></property><property name="text"><string>LED</string></property></widget><widget class="QLabel" name="label"><property name="geometry"><rect><x>260</x><y>80</y><width>71</width><height>41</height></rect></property><property name="text"><string>TextLabel</string></property></widget><widget class="QLabel" name="label_2"><property name="geometry"><rect><x>260</x><y>160</y><width>71</width><height>31</height></rect></property><property name="text"><string>TextLabel</string></property></widget></widget><widget class="QMenuBar" name="menubar"><property name="geometry"><rect><x>0</x><y>0</y><width>800</width><height>22</height></rect></property></widget><widget class="QStatusBar" name="statusbar"/></widget><resources/><connections/>
</ui>
从这个xml文件中,我们可以看到有三个图形,名字分别为:pushButton、label、label_2。
这里不妨先把文件mainwindow.ui
保存一下,快捷键CTRL+S。
然后我们要给pushButton
这个图形添加回调函数。
为pushButton
这个图形添加回调函数
打开 Headers→mainwindow.h
把下面的代码:
private slots:void on_pushButton_clicked();
复制到下面的位置:
作用是对函数on_pushButton_clicked
进行声明,当然是在类MainWindow
中进行声明。
其中的关键词slots
的作用见我的另一篇博文 https://blog.csdn.net/wenhao_ir/article/details/145421581
上面代码中的Q_OBJECT
的解释如下:
Q_OBJECT
是 Qt 中的一个宏,通常出现在声明继承自 QObject
的类中(如 QMainWindow
)。它是 Qt 的元对象系统的一部分,用来启用类的信号和槽机制、事件处理等功能。
然后去文件mainwindow.cpp中去实现函数on_pushButton_clicked
:
我们在类的外部去定义它,代码如下:
void MainWindow::on_pushButton_clicked()
{qDebug()<<"LED clicked";
}
上面的函数 qDebug()
需要引入头文件#include <QDebug>
,写完后,文件mainwindow.cpp中的完整代码如下:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::on_pushButton_clicked()
{qDebug()<<"LED clicked";
}
这段代码就是开头几句不太好理解,那个其实是类的构造函数的初始化列表,详情见 https://blog.csdn.net/wenhao_ir/article/details/145422254
看完上面这篇博文后就可以分析下面的代码了:
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);
}
首先要知道这个类的原型其实是定义在Headers→mainwindow.h
中的,其完整定义如下:
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void on_pushButton_clicked();private:Ui::MainWindow *ui;
};
上面代码中的Q_OBJECT
的解释如下:
Q_OBJECT
是 Qt 中的一个宏,通常出现在声明继承自 QObject
的类中(如 QMainWindow
)。它是 Qt 的元对象系统的一部分,用来启用类的信号和槽机制、事件处理等功能。
Ui
是一个命名空间,这个在以前使用OpenCV时已经比较熟悉了。
回到对下面代码的分析:
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);
}
这是在类MainWindow的声明外定义类MainWindow的构造函数,它的作用是初始化 MainWindow 界面。我们来详细解析其中的语法和逻辑:
这段代码是 MainWindow
类的 构造函数,它的作用是初始化 MainWindow
界面。我们来详细解析其中的语法和逻辑:
1. MainWindow::MainWindow(QWidget *parent)
MainWindow
是类的构造函数,MainWindow(QWidget *parent)
表示它可以接收一个QWidget *parent
指针,默认情况下,这个parent
可能为空(即nullptr
)。parent
参数用于 Qt 的 父子对象机制,确保在销毁parent
时,其子对象(即MainWindow
的实例)也会被自动销毁,避免内存泄漏。
2. QMainWindow(parent)
- 这个是 初始化列表中的一项内容,关于初始化列表的详细介绍见博文 https://blog.csdn.net/wenhao_ir/article/details/145422254
:QMainWindow(parent)
调用了QMainWindow
的构造函数,并将parent
传递给它。QMainWindow
是MainWindow
的基类,这样可以正确初始化QMainWindow
的内部成员,使MainWindow
继承窗口管理的功能。
3. ui(new Ui::MainWindow)
- 这个也是 初始化列表中的一项内容,关于初始化列表的详细介绍见博文 https://blog.csdn.net/wenhao_ir/article/details/145422254
ui
是一个指向Ui::MainWindow
的指针【Ui:是一个命名空间】,通过new Ui::MainWindow
在堆上创建 UI 界面对象(ui
由 Qt Designer 生成)。- 这里
Ui::MainWindow
负责界面元素的管理,比如按钮、标签、文本框等。
4. ui->setupUi(this);
setupUi(this)
这个函数由Qt Designer
生成,它的作用是:- 将
ui
设计的界面组件添加到MainWindow
界面上。 - 自动连接 Qt Designer 里设定的信号和槽(如果使用了 Qt 的自动连接机制)。
- 初始化 UI 控件,比如设置按钮的名称、默认状态等。
- 将
小结
该构造函数的作用是:
- 调用基类
QMainWindow
的构造函数,确保MainWindow
作为窗口正确初始化。 - 创建
Ui::MainWindow
实例,用于管理 UI 界面。 - 调用
setupUi(this);
,设置 UI 界面元素,使其在MainWindow
窗口上可见。
你可以理解成:
QMainWindow(parent)
负责窗口管理;ui(new Ui::MainWindow)
负责界面管理;ui->setupUi(this)
负责把界面元素加载到MainWindow
中。
这样 MainWindow
才能正确显示界面,并响应用户操作。
编译工程
编译的时候右下角会提示编译进度。
有两个警告不用管(因为不是语法上的错,只是配置上的一点瑕疵):
编译出的结果在工程目录中,具体如下:
上图中的test_01
就是生成的可执行程序。
我们可以按照博文 https://blog.csdn.net/wenhao_ir/article/details/144651612 的方法查看下它是不是运行于ARM架构上的可执行文件,这样可以检查我们的gcc编译器是否配置正确。
file /home/book/Qt_project/Q001_test_01/build-test_01-qt_kit_swh_01-Debug/test_01
运行结果如下:
/test_01: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-, for GNU/Linux 4.9.0, not stripped
从中可以看出,它是ARM架构的,并且需要动态链接库的支持,所以需要检查开发板上有没有配置Qt运行环境,我在博文 https://blog.csdn.net/wenhao_ir/article/details/145367198 【搜索“那么如何判断开发板上有没有配置Qt运行环境呢”】中已经检查过了。
把test_01
放到NFS文件系统的目录中:
关闭开发板上QT的GUI(选做)
注意:后来我发现其实这一步并不需要。没有这一步测试程序同样能正常运行并且显示出测试程序绘制GUI界面
注意:后来我发现其实这一步并不需要。没有这一步测试程序同样能正常运行并且显示出测试程序绘制GUI界面
注意:后来我发现其实这一步并不需要。没有这一步测试程序同样能正常运行并且显示出测试程序绘制GUI界面
打开串口终端→打开开发板
参考博文 https://blog.csdn.net/wenhao_ir/article/details/144591685 用一次性有效的方法(即不是永久有效的方法)关掉自带的QT的GUI界面。
这里用一次性的方法,即不是永久有效的方法:
执行下面这条命令:
/etc/init.d/S99myirhmi2 stop
执行完成后再用手去操作屏幕上的UI界面,UI界面就没有任何反应了,说明QT的GUI界面被关掉了。
禁止LCD黑屏(选做)
注意:后来我发现其实这一步并不一定需要,因为很多时候我们的测试时间都是比较短的。
注意:后来我发现其实这一步并不一定需要,因为很多时候我们的测试时间都是比较短的。
注意:后来我发现其实这一步并不一定需要,因为很多时候我们的测试时间都是比较短的。
关闭开发析上QT的GUI后,还需要禁止LCD黑屏,否则过一会儿LCD会黑屏,用下面的命令实现:
echo -e "\033[9;0]" > /dev/tty0
这条命令的详细解释见 https://blog.csdn.net/wenhao_ir/article/details/145431203
设置Qt运行的环境变量
export QT_QPA_GENERIC_PLUGINS=tslib:/dev/input/event1
export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0
export QT_QPA_FONTDIR=/usr/lib/fonts/
上面三条命令的详细解释见 https://blog.csdn.net/wenhao_ir/article/details/145433648 【这篇博文中包含第1条命令生效的必要条件,还包括如果让三条命令一直有效的方法,可以看一下。】
运行Qt程序
挂载网络文件系统
mount -t nfs -o nolock,vers=3 192.168.5.11:/home/book/nfs_rootfs /mnt
然后运行我们编译出的Qt测试程序:
注意:运行前请确保Qt运行的环境变量设置好了。
注意:运行前请确保Qt运行的环境变量设置好了。
/mnt/qt_test01/test_01
运行结果如下:
提示先不用管,这是正常的,教程视频中也有这样的提示。
同时,屏幕上也出现了我们用Qt绘制的界面:
然后用手点击LED
按钮…
发现每点击一次就打印出一次字符串“LED clicked”,这样测试就成功了。
如何让程序在系统启动时运行
参考:博文 https://blog.csdn.net/wenhao_ir/article/details/144591685 【查看“永久有效的关掉QT的GUI界面最简单的方法”】 和 视频 https://www.bilibili.com/video/BV1HT421k7GW/?spm_id_from=333.1391.0.0&p=7&vd_source=8fb767d1739ea6b35c7177ba909eed36【10分15秒开始看,并且要看把视频看完了再开始做,因为视频中第1次的方法是有问题的。】
附完整源代码
mainwindow.ui 中的代码
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"><class>MainWindow</class><widget class="QMainWindow" name="MainWindow"><property name="geometry"><rect><x>0</x><y>0</y><width>800</width><height>600</height></rect></property><property name="windowTitle"><string>MainWindow</string></property><widget class="QWidget" name="centralwidget"><widget class="QPushButton" name="pushButton"><property name="geometry"><rect><x>90</x><y>130</y><width>89</width><height>25</height></rect></property><property name="text"><string>LED</string></property></widget><widget class="QLabel" name="label"><property name="geometry"><rect><x>260</x><y>80</y><width>71</width><height>41</height></rect></property><property name="text"><string>TextLabel</string></property></widget><widget class="QLabel" name="label_2"><property name="geometry"><rect><x>260</x><y>160</y><width>71</width><height>31</height></rect></property><property name="text"><string>TextLabel</string></property></widget></widget><widget class="QMenuBar" name="menubar"><property name="geometry"><rect><x>0</x><y>0</y><width>800</width><height>22</height></rect></property></widget><widget class="QStatusBar" name="statusbar"/></widget><resources/><connections/>
</ui>
mainwindow.h 中的代码
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void on_pushButton_clicked();private:Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp 中的代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::on_pushButton_clicked()
{qDebug()<<"LED clicked";
}
main.cpp 中的代码
#include "mainwindow.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);MainWindow w;w.show();return a.exec();
}
附编译完成后完整的工程目录
https://pan.baidu.com/s/1yhnmQGpnYl2I-urBsQt5Ew?pwd=88iw
注意:QtCreator的工程换位置后一定要更换一下Build directory的位置,因为在QtCreator中Build directory是一个绝对路径,详情见 https://blog.csdn.net/wenhao_ir/article/details/145458743