2. 窗口可视化设计–点亮LED¶
前面熟悉了Qt的工程创建和部署运行等,这章将简单学习下Qt界面设计。一般界面设计可以通过Qt Designer 进行可视化设计,或者代码化UI设计。
这章主要使用Qt Designer 进行可视化设计,设计一个非常简单的UI,控制鲁班猫板卡的GPIO,点亮一个LED。
提示
实际界面设计会混合使用代码和图形可视化,图形化设计很简单直观(所见即所得),代码化设计更灵活,可以实现一些图形化设计做不到的效果,也便于后期修改维护。
2.1. 鲁班猫板卡GPIO资源介绍¶
鲁班猫板卡引出了的40 pin引脚(Lubancat2为例):
可以看到引脚可以复用为多种功能,这章我们只是使用普通io功能,点亮一个led。这里教程测试的板卡是lubancat2,默认使用的引脚是GPIO3_A5。 更多硬件资源或者其他板卡引脚参考下 这里
2.2. libgpiod¶
在Linux中,最常见的读写GPIO方式就是用GPIO sysfs interface, 是通过 /sys/class/gpio 目录下的 export 、 unexport 、gpio{N}/direction, gpio{N} /value (用实际引脚号替代{N})等文件实现, 命令行直接对data和direction等文件的读写来简便地操作IO。
从kernel 4.8开始,使用GPIO character device API,暴露到用户空间的设备文件是/dev/gpiochipN,新接口的设备文件没法像之前的sysfs接口一样使用, 而是通过作用在设备文件上的一系列ioctl实现的,这比较底层而不方便使用,因此一个建立在其上的封装库libgpiod应运而生。
相比sysfs接口,使用libgpiod操作/dev/gpiochipN有更多优势:
为设置IO的上下拉提供了统一的操作;
提供了用户空间中断的原生支持;
可以在一个系统调用的时间内同时读取或者设置多个IO的值。此前操作多个IO必须分别对每个IO对应的设备文件进行read/write,相比之下新的接口不但节省了开销, 更可以对多个IO电平变化的时机进行精确的同步。
鲁班猫板卡系统中使用libgpiod库,需要使用apt命令安装:
# 使用命令安装libgpiod的相关库和头文件
sudo apt install libgpiod-dev
2.3. Qt Designer介绍¶
Qt Designer 是一个Qt工具,用于设计和构建图形用户界面(GUI)。
创建一个普通项目,默认勾选窗体(form)复选框,就会创建一个.ui文件,双击该文件就可以打开Qt Designer界面。
Qt Designer的使用参考下: 野火Qt Designer教程 , 更多的一些可以查看Qt官网的 Qt Designer教程 。
2.4. 点亮LED例程¶
2.4.1. 创建一个GPIO控制工程¶
打开Qt Creator,新建工程项目,创建一个qt_gpio工程,具体创建参考下前面 Hello Qt 章节。创建工程后,会在对应目录下生成:
创建的项目默认添加了界面文件(默认勾选窗体(form)复选框),就会产生上面的mainwindow.ui文件。
2.4.2. 简单UI设计¶
双击项目资源目录的mainwindow.ui文件,进入设计界面,先点击主窗口(这里测试创建的是QMainWindow,个人测试可以使用QWidget), 在属性栏中设置大小为640x480,并设置最大值和最小值相同来固定窗口大小:
从左边的控件面板中拖两个按键控件(QPushButton)到主窗口,实际就是添加两个按键对象到主窗口,我们重新修改对象名称分别为BtnRED、BtnONOFF:
然后我们修改下两个按键控件的大小和相对主窗口的位置,先点击对象浏览框中的BtnONOFF,然后在属性栏然后修改, 在QWidget属性修改位置和大小:
设置按钮文本和可选的:
提示
前面图片中,属性栏中可以清晰的看见QPushButton类的继承关系:QObject->QWidget->QAbstractButton->QPushButton
添加资源文件,更改按键控件的样式。先到工程目录下点击 添加新文件
,选择添加 Qt Resource File
之后设置下名称,然后一路点击完成:
然后选择配套例程img文件下一些图片,添加到工程中,然后保存:
再打开mainwindow.ui的Qt Designer界面,右击BtnRED或者BtnONOFF,点击 更改样式表
,选择 添加资源
,下拉框中选择 border-image
,
然后选择前面添加图片来填充控件,BtnRED使用c_btn.png:
关闭资源文件后,如果需要继续添加其他资源文件,可以右击.qrc资源文件,找到用 资源编辑器
打开 ,就可以继续添加资源文件。
修改之后,我们可以先选择虚拟机系统的默认套件: Desktop Qt %{Qt:Version} GCC 64bit
,编译运行下,查看我们设计的简单窗口:
2.4.3. 编写GPIO控制程序¶
在工程目录右击选择 添加新文件
,添加一个c++类,名称是GpioLed :
添加之后,在类中描述,添加初始化和设置gpio输出高低电平的函数接口(使用libgpiod):
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 | #ifndef GPIOLED_H
#define GPIOLED_H
#include <QDebug>
extern "C"{
#include <gpiod.h>
}
class GpioLed : public QObject
{
Q_OBJECT
public:
/*测试使用引脚GPIO3_A5,实际根据鲁班猫板卡引脚修改*/
const char *chipname = "gpiochip3";
int line_num = 5;
struct gpiod_chip *chip;
struct gpiod_line *line_led;
public:
int init();
void set_value(bool flag);
explicit GpioLed(QObject *parent = nullptr);
~GpioLed();
signals:
};
#endif // GPIOLED_H
|
函数具体实现在gpioled.cpp:
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 | int GpioLed::init()
{
int ret;
/* 打开GPIO控制器 */
chip = gpiod_chip_open_by_name(chipname);
if (!chip)
{
qDebug("gpiod_chip_open_by_name failed!");
return -1;
}
/* 获取引脚 */
line_led = gpiod_chip_get_line(chip, line_num);
if (!line_led)
{
gpiod_chip_close(chip);
qDebug("gpiod_chip_get_line failed!");
return -1;
}
/* 配置引脚为输出模式 name为“led” 初始电平为high ;教程的测试的电路,gpio输出为低电平时led亮*/
ret = gpiod_line_request_output(line_led, "led", 1);
if (ret)
{
qDebug("led request error.");
return -1;
}
return 0;
}
void GpioLed::set_value(bool flag)
{
gpiod_line_set_value(line_led, flag?1:0);
}
|
然后在我们的mainwindow中初始化:
1 2 3 4 5 6 7 8 9 10 11 12 | class MainWindow : public QMainWindow
{
Q_OBJECT
public:
// 创建对象GPIO3_A5
GpioLed GPIO3_A5;
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
//后面省略
|
1 2 3 4 5 6 7 8 9 10 11 | MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
/*设置使用的GPIO,调用函数初始化GPIO3_A5输出*/
GPIO3_A5.chipname="gpiochip3";
GPIO3_A5.line_num=5;
GPIO3_A5.init();
}
|
以上就是一个非常简陋的gpio控制程序,实际使用可以自己添加更多的函数。
2.4.4. 关联信号与槽¶
前面创建了界面,实现了GPIO的控制,现在需要关联按钮点击和gpio的操作,来实现点击按键控件,就点亮LED。
进入Qt Creator设计界面,右击BtnONOFF按钮, 在弹窗中选择 转为槽...
,选中clicked(bool):
会在mainwindow中自动添加on_BtnOnOff_clicked(bool checked)函数,我们在该函数下添加一些操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | void MainWindow::on_BtnOnOff_clicked(bool checked)
{
if(checked)
{
/*按键控件按下on,checked=ture ,gpio输出低电平,led亮*/
GPIO3_A5.set_value(!checked);
/*改变按键样式*/
ui->BtnOnOff->setStyleSheet(QString::fromUtf8("border-image: url(:/ic_btn_pre.png);"));
ui->BtnRED->setStyleSheet(QString::fromUtf8("border-image: url(:/led_red.png);"));
}
else
{
/*按键控件off,checked=false ,gpio输出高电平,led灭*/
GPIO3_A5.set_value(!checked);
/*改变按键样式*/
ui->BtnOnOff->setStyleSheet(QString::fromUtf8("border-image: url(:/ic_btn.png);"));
ui->BtnRED->setStyleSheet(QString::fromUtf8("border-image: url(:/led_off.png);"));
}
}
|
也许会有这样的疑问,怎么没有使用connect函数关联信号与槽? 到项目构建目录下,会看到一个中间文件:ui_mainwindow.h (对应测试默认创建的mainwindow.ui),打开文件会看到其中会有这么一句:
1 | QMetaObject::connectSlotsByName(MainWindow);
|
该函数会将递归的搜寻传入的Qt对象object的所有子对象,并把所有匹配的子对象的信号关联到object对象的符合规则的槽函数: void on_<窗口部件名称>_<信号名称>(<信号参数>), 如果窗口部件已经提供信号,就可以自动关联。更多信号与槽的知识参考下后面章节。
提示
在窗口设计中一些看不懂的函数或者不知道如何使用,可以先查看下Qt Creator中的帮助文档(快捷键F1)。
2.5. 运行测试例程¶
项目选择 LubanCat_RK
编译套件,然后打开qt_gpio.pro文件,修改下的下载路径和添加libgpiod链接库:
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 | QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
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 += \
gpioled.cpp \
main.cpp \
mainwindow.cpp
HEADERS += \
gpioled.h \
mainwindow.h
FORMS += \
mainwindow.ui
# 添加链接库
LIBS += -lgpiod
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
#else: unix:!android: target.path = /opt/$${TARGET}/bin
# 修改下部署路径,如果不是远程部署,不需要设置
else: unix:!android: target.path = /home/cat/qt/qt_gpio
!isEmpty(target.path): INSTALLS += target
RESOURCES += \
img/img.qrc
|
之后点击Qt Creator左下角锤子,只进行编译,编译后会在构建目录下生成qt_gpio可执行文件。 传输到板卡执行程序:
# 复制可执行程序到板卡
scp qt_gpio cat@192.168.103.110:/home/cat/qt
# 在debian10 带桌面的系统中运行,使用X11
./qt_gpio -platform xcb
在桌面就会弹窗,然后我们点击按钮就会点亮或者关闭LED(如果相应引脚接了LED),相应的图标也会变化:
也可以远程部署,参考下前面章节。