- 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
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
从这个xml文件中,我们可以看到有三个图形,名字分别为:pushButton、label、label_2。
这里不妨先把文件mainwindow.ui
保存一下,快捷键CTRL+S。
然后我们要给pushButton
这个图形添加回调函数。
为pushButton
这个图形添加回调函数
打开 Headers→mainwindow.h

把下面的代码:
private slots:
void on_pushButton_clicked();
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
复制到下面的位置:

作用是对函数on_pushButton_clicked
进行声明,当然是在类MainWindow
中进行声明。
其中的关键词slots
的作用见我的另一篇博文 http://iyenn.com/rec/1709316.html
上面代码中的Q_OBJECT
的解释如下:
Q_OBJECT
是 Qt 中的一个宏,通常出现在声明继承自 QObject
的类中(如 QMainWindow
)。它是 Qt 的元对象系统的一部分,用来启用类的信号和槽机制、事件处理等功能。
mainwindow.cpp中的关键代码解释
然后去文件mainwindow.cpp中去实现函数on_pushButton_clicked
:

我们在类的外部去定义它,代码如下:
void MainWindow::on_pushButton_clicked()
{
qDebug()<<"LED clicked";
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
上面的函数 qDebug()
需要引入头文件#include
,写完后,文件mainwindow.cpp中的完整代码如下:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include
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";
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
这段代码就是开头几句不太好理解,那个其实是类的构造函数的初始化列表,详情见 http://iyenn.com/rec/1709317.html
看完上面这篇博文后就可以分析下面的代码了:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
首先要知道这个类的原型其实是定义在Headers→mainwindow.h
中的,其完整定义如下:
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
};
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
上面代码中的Q_OBJECT
的解释如下:
Q_OBJECT
是 Qt 中的一个宏,通常出现在声明继承自 QObject
的类中(如 QMainWindow
)。它是 Qt 的元对象系统的一部分,用来启用类的信号和槽机制、事件处理等功能。
Ui
是一个命名空间,这个在以前使用OpenCV时已经比较熟悉了。
回到对下面代码的分析:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
这是在类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)
- 这个是 初始化列表中的一项内容,关于初始化列表的详细介绍见博文 http://iyenn.com/rec/1709317.html
:QMainWindow(parent)
调用了 QMainWindow
的构造函数,并将 parent
传递给它。QMainWindow
是 MainWindow
的基类,这样可以正确初始化 QMainWindow
的内部成员,使 MainWindow
继承窗口管理的功能。
3. ui(new Ui::MainWindow)
- 这个也是 初始化列表中的一项内容,关于初始化列表的详细介绍见博文 http://iyenn.com/rec/1709317.html
- 由于
Ui
是一个命名空间,所以 Ui::MainWindow
类和咱们这里代码中的MainWindow
类是两个不同的类。 Ui::MainWindow
类用于操作 UI 组件,比如 QPushButton
(按钮)、QLabel
(标签)、文本框等。ui
是一个指向 Ui::MainWindow
类的对象实例的指针,new Ui::MainWindow
创建了 Ui::MainWindow
类的一个实例,并将其赋值给指针 ui
。- 由于
ui
是一个指针,所以需要使用 new
来为其分配内存。
4. ui->setupUi(this);
setupUi()
这个函数由 Qt Designer
生成,它的作用是:
- 将
ui
设计的界面组件添加到 MainWindow
界面上。 - 自动连接 Qt Designer 里设定的信号和槽(如果使用了 Qt 的自动连接机制)。
- 初始化 UI 控件,比如设置按钮的名称、默认状态等。
- 关于关键词
this
的详细解释见 http://iyenn.com/rec/1709318.html ui->setupUi(this);
这句话将类 Ui::MainWindow
的实例对象ui
与类 MainWindow
的实例对象绑定起来,换句话说,它会把 mainwindow.ui
里定义的所有控件创建出来并绑定到 MainWindow
类的 this
对象。
小结
该构造函数的作用是:
- 调用基类
QMainWindow
的构造函数,确保 MainWindow
作为窗口正确初始化。 - 创建
Ui::MainWindow
实例,用于管理 UI 界面。 - 调用
setupUi(this);
,设置 UI 界面元素,使其在 MainWindow
窗口上可见。
你可以理解成:
QMainWindow(parent)
负责窗口管理;ui(new Ui::MainWindow)
负责界面管理;ui->setupUi(this)
负责把界面元素加载到 MainWindow
中。
这样 MainWindow
才能正确显示界面,并响应用户操作。
编译工程

编译的时候右下角会提示编译进度。

有两个警告不用管(因为不是语法上的错,只是配置上的一点瑕疵):

编译出的结果在工程目录中,具体如下:


上图中的test_01
就是生成的可执行程序。
我们可以按照博文 http://iyenn.com/rec/1709246.html 的方法查看下它是不是运行于ARM架构上的可执行文件,这样可以检查我们的gcc编译器是否配置正确。
file /home/book/Qt_project/Q001_test_01/build-test_01-qt_kit_swh_01-Debug/test_01
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
运行结果如下:
/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
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
从中可以看出,它是ARM架构的,并且需要动态链接库的支持,所以需要检查开发板上有没有配置Qt运行环境,我在博文 http://iyenn.com/rec/1709264.html 【搜索“那么如何判断开发板上有没有配置Qt运行环境呢”】中已经检查过了。
把test_01
放到NFS文件系统的目录中:

关闭开发板上自带的QT的GUI
经实测,如果不关闭开发板自带的QT的GUI,虽然你自己写的Qt界面能加载出来,但是当你用手划动屏幕时,开发板上自带的QT的GUI有可能会弹出来。
参考博文 http://iyenn.com/rec/1709315.html 用一次性有效的方法(即不是永久有效的方法)关掉自带的QT的GUI界面。
这里用一次性的方法,即不是永久有效的方法:
执行下面这条命令:
/etc/init.d/S99myirhmi2 stop
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
执行完成后再用手去操作屏幕上的UI界面,UI界面就没有任何反应了,说明QT的GUI界面被关掉了。
禁止LCD黑屏(选做)
注意:后来我发现其实这一步并不一定需要,因为很多时候我们的测试时间都是比较短的。
注意:后来我发现其实这一步并不一定需要,因为很多时候我们的测试时间都是比较短的。
注意:后来我发现其实这一步并不一定需要,因为很多时候我们的测试时间都是比较短的。
关闭开发析上QT的GUI后,还需要禁止LCD黑屏,否则过一会儿LCD会黑屏,用下面的命令实现:
echo -e "\033[9;0]" > /dev/tty0
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
这条命令的详细解释见 http://iyenn.com/rec/1709319.html
设置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/
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
上面三条命令的详细解释见 http://iyenn.com/rec/1709052.html 【这篇博文中包含第1条命令生效的必要条件,还包括如果让三条命令一直有效的方法,可以看一下。】
运行Qt程序
挂载网络文件系统
mount -t nfs -o nolock,vers=3 192.168.5.11:/home/book/nfs_rootfs /mnt
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
然后运行我们编译出的Qt测试程序:
注意:运行前请确保Qt运行的环境变量设置好了。
注意:运行前请确保Qt运行的环境变量设置好了。
/mnt/qt_test01/test_01
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
运行结果如下:

提示先不用管,这是正常的,教程视频中也有这样的提示。
同时,屏幕上也出现了我们用Qt绘制的界面:

然后用手点击LED
按钮…

发现每点击一次就打印出一次字符串“LED clicked”,这样测试就成功了。
如何让程序在系统启动时运行
参考:博文 http://iyenn.com/rec/1709315.html 【查看“永久有效的关掉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>
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">
- 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
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
mainwindow.h 中的代码
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
};
#endif
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">
- 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
mainwindow.cpp 中的代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include
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";
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
main.cpp 中的代码
#include "mainwindow.h"
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
附编译完成后完整的工程目录
https://pan.baidu.com/s/1yhnmQGpnYl2I-urBsQt5Ew?pwd=88iw
注意:QtCreator的工程换位置后一定要更换一下Build directory的位置,因为在QtCreator中Build directory是一个绝对路径,详情见 http://iyenn.com/rec/1709289.html
data-report-view="{"mod":"1585297308_001","spm":"1001.2101.3001.6548","dest":"https://blog.csdn.net/wenhao_ir/article/details/145420998","extend1":"pc","ab":"new"}">>
id="blogExtensionBox" style="width:400px;margin:auto;margin-top:12px" class="blog-extension-box"> class="blog_extension blog_extension_type5" id="blog_extension">
class="extension_official" data-report-click="{"spm":"1001.2101.3001.6471"}" data-report-view="{"spm":"1001.2101.3001.6471"}">
class="blog_extension_card_left">
class="blog_extension_card_cont">
昊虹嵌入式技术交流群
class="blog_extension_card_cont_r">
QQ群名片
评论记录:
回复评论: