第一个Qt开发实例(一个Push Button按钮和两个Label)【包括如何在QtCreator中创建新工程、代码详解、编译、环境变量配置、测试程序运行等】

Qt开发环境QtCreator的安装、配置

详情见 https://blog.youkuaiyun.com/wenhao_ir/article/details/145367198

在QtCreator中创建新工程

在这里插入图片描述
在这里插入图片描述
然后设置工程的名字和位置:
在这里插入图片描述
上图中点击Next…
我们这里使用qmake进行构建,所以选择qmake:
在这里插入图片描述
上图中继续点击Next…
在这里插入图片描述
这里是设置Qt的C++代码中类的名字和相关文件的名字,这些使用默认的就可以了。

上图中继续点击Next…
在这里插入图片描述
上图是设置语言的转换,不是编译语言的转换哈,就是英语、汉语、法语的那种语言,我们不需要作这个操作,所以继续Next。
在这里插入图片描述
在这里插入图片描述
这里选择在博文 https://blog.youkuaiyun.com/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.youkuaiyun.com/wenhao_ir/article/details/145421581

上面代码中的Q_OBJECT的解释如下:
Q_OBJECT 是 Qt 中的一个宏,通常出现在声明继承自 QObject 的类中(如 QMainWindow)。它是 Qt 的元对象系统的一部分,用来启用类的信号和槽机制、事件处理等功能。

mainwindow.cpp中的关键代码解释

然后去文件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.youkuaiyun.com/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_NAMESPACE


class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    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.youkuaiyun.com/wenhao_ir/article/details/145422254
  • :QMainWindow(parent) 调用了 QMainWindow 的构造函数,并将 parent 传递给它。
  • QMainWindowMainWindow 的基类,这样可以正确初始化 QMainWindow 的内部成员,使 MainWindow 继承窗口管理的功能。

3. ui(new Ui::MainWindow)

  • 这个也是 初始化列表中的一项内容,关于初始化列表的详细介绍见博文 https://blog.youkuaiyun.com/wenhao_ir/article/details/145422254
  • 由于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的详细解释见 https://blog.youkuaiyun.com/wenhao_ir/article/details/145512865
  • ui->setupUi(this);这句话将类 Ui::MainWindow 的实例对象ui与类 MainWindow的实例对象绑定起来,换句话说,它会把 mainwindow.ui 里定义的所有控件创建出来绑定到 MainWindow类的 this对象

小结
该构造函数的作用是:

  1. 调用基类 QMainWindow 的构造函数,确保 MainWindow 作为窗口正确初始化。
  2. 创建 Ui::MainWindow 实例,用于管理 UI 界面。
  3. 调用 setupUi(this);,设置 UI 界面元素,使其在 MainWindow 窗口上可见。

你可以理解成:

  • QMainWindow(parent) 负责窗口管理;
  • ui(new Ui::MainWindow) 负责界面管理;
  • ui->setupUi(this) 负责把界面元素加载到 MainWindow 中。

这样 MainWindow 才能正确显示界面,并响应用户操作。

编译工程

在这里插入图片描述
编译的时候右下角会提示编译进度。
在这里插入图片描述

有两个警告不用管(因为不是语法上的错,只是配置上的一点瑕疵):
在这里插入图片描述
编译出的结果在工程目录中,具体如下:
在这里插入图片描述
在这里插入图片描述
上图中的test_01就是生成的可执行程序。
我们可以按照博文 https://blog.youkuaiyun.com/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.youkuaiyun.com/wenhao_ir/article/details/145367198 【搜索“那么如何判断开发板上有没有配置Qt运行环境呢”】中已经检查过了。

test_01放到NFS文件系统的目录中:
在这里插入图片描述

关闭开发板上自带的QT的GUI

经实测,如果不关闭开发板自带的QT的GUI,虽然你自己写的Qt界面能加载出来,但是当你用手划动屏幕时,开发板上自带的QT的GUI有可能会弹出来。

参考博文 https://blog.youkuaiyun.com/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.youkuaiyun.com/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.youkuaiyun.com/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.youkuaiyun.com/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_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    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.youkuaiyun.com/wenhao_ir/article/details/145458743

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

昊虹AI笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值