文章目录

  • 前言
  • 1、配置双架构 Qt kits
  • 1.1 x86 架构的 Qt 库安装
  • 2.2 安装32位armQT4开发环境
  • 2.2.1 安装必要依赖和库
  • 2.2.2 配置交叉工具链
  • 2.2.2 导入qt4库和tslib库
  • 2.2.2.1 导出qt4-arm和tslib-arm
  • 2.2.2.2 将qt4-arm和tslib-arm导入到新的ubuntu系统中
  • 2.2.3 配置qtcreator Kit
  • 2、 Qt常用的按钮控件
  • 3、Push Button 按钮编程
  • 3.1 程序完成后的执行结果
  • 3.2 生成项目
  • 3.3 完成代码编辑
  • 3.3.1 修改项目文件 _qpushbutton.pro
  • 3.3.2 修改`main.cpp`
  • 3.3.3 修改`widget.h`
  • 3.3.4 修改`widget.cpp`
  • 3.4 切换Kit,获得运行在不同系统中的运行的执行文件
  • 3.5 程序中用到的QT机制
  • 3.4.1 信号(Signal)和槽(Slot)
  • 3.4.2 样式表
  • 总结



前言

使用实际编程的方法学习 Qt 控件,可以更好地理解和掌握按钮控件的特性和应用,同时还可以提高编程技能并增强对 Qt 框架的认识。
我们将通过几篇系列文章,介绍QT常用按钮编程。
本文介绍QT常用控件的第一个按钮,Push Button按钮编程。通过这个例子,初步了解QT的信号与槽、样式表等机制,此外,我们的调试环境配置了双架构Kits,使得编译调试可以在当前的ubuntu中进行,也可以重新编译后下载到目标arm设备中运行。
我们的编程环境为:Ubuntu64位系统(22.04),目标架构:(1)qt5 x86_64 架构,(2)qt4 32位arm架构。


1、配置双架构 Qt kits

在开发环境中,我们使用的是 x86_64 架构的 Ubuntu 22.04 虚拟机,而目标设备是使用 32 位 ARM 架构的系统。为了提高开发效率,我们在调试环境中同时配置了 x86 架构的 Qt 库。这样,在进行 Qt 界面开发和调试时,我们可以在 Ubuntu 上直接进行。在满意后,切换kit,重新编译后将应用程序下载到目标设备中进行测试和运行。由于减少了下载次数,大大提高了工作效率。

1.1 x86 架构的 Qt 库安装

虽然在 Qt5 中添加了很多新的功能和模块,但是对于常用控件,它们与 Qt4 中的版本基本相同,可以使用相同的方法和属性进行操作。
我们在 Ubuntu 22.04 虚拟机直接安装QT5和qtcreator:

sudo apt-get install build-essential
sudo apt-get install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools
sudo apt-get install qtcreator

qtcreator所有的配置采用默认。

2.2 安装32位armQT4开发环境

2.2.1 安装必要依赖和库

(1)安装 lib32stdc++6 软件包来解决。

sudo apt-get install lib32stdc++6

(2)安装依赖

sudo apt-get install build-essential libfontconfig1 mesa-common-dev libglu1-mesa-dev libpulse-dev libicu-dev libsqlite3-dev libssl-dev libxcb-xinerama0-dev libxkbcommon-dev libxkbcommon-x11-dev libasound2-dev libgstreamer-plugins-base1.0-dev libgstreamer1.0-dev

(3)安装32位 cc1组件

sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install zlib1g:i386

2.2.2 配置交叉工具链

  • 将过去备份的交叉工具链gcc-linaro-arm-linux-gnueabihf-4.7-2013.03-20130313_linux.tar.gz,拷贝到/opt,解压:
sudo tar -zxvf gcc-linaro-arm-linux-gnueabihf-4.7-2013.03-20130313_linux.tar.gz
  • 将解压缩的工具链目录添加到环境变量中,例如添加以下行到 ~/.bashrc 文件最后:
vim ~/.bashrc
export PATH=$PATH:/opt/gcc-linaro-arm-linux-gnueabihf-4.7-2013.03-20130313_linux/bin
  • 运行 source ~/.bashrc 命令以更新环境变量。
source ~/.bashrc
  • 验证一下:
arm-linux-gnueabihf-gcc -v

成功:

。。。
gcc version 4.7.3 20130226 (prerelease) (crosstool-NG linaro-1.13.1-4.7-2013.03-20130313 - Linaro GCC 2013.03)

2.2.2 导入qt4库和tslib库

2.2.2.1 导出qt4-arm和tslib-arm

我们将按照《Ubuntu64位系统(v18.04)下arm32位版本(Qt4.8.6和tslib1.4)开发环境搭建》第5节的方法完成的QT4库qt4-arm文件夹和第4节完成的tslib-arm文件夹压缩。

tar -czvf qt4-arm.tar.gz qt4-arm
 tar -czvf tslib-arm.tar.gz tslib-arm

得到两个压缩文件:qt4-arm.tar.gztslib-arm.tar.gz

2.2.2.2 将qt4-arm和tslib-arm导入到新的ubuntu系统中

拷贝qt4-arm.tar.gztslib-arm.tar.gz到当前的ubuntu系统中,解压。

tar -zxvf qt4-arm.tar.gz
tar -zxvf tslib-arm.tar.gz

注意:需要将这两个文件放在与导出ubuntu系统相同的绝对路径下。

2.2.3 配置qtcreator Kit

  • 配置Qt Versions
    打开 Qt Creator,选择「工具」-「选项」-「构建和运行」 - 「Qt Versions」,界面如图:
  • 配置编译器
    为qtcreator配置交叉工具链,切换到 「编译器」,点击「添加」,选择GCC,添加C和C++交叉工具链路径,结果如下图:
  • 配置Kits
    切换到

有关这部分的详细内容,请参考前面的两篇博文《Ubuntu64位系统(v18.04)下arm32位版本(Qt4.8.6和tslib1.4)开发环境搭建》和《Ubuntu64位系统(20.04、22.04)安装32位armQT4开发环境补充说明》。

2、 Qt常用的按钮控件

ios pushViewController不生效的原因 push-button neanderthal_QT


这些都是 Qt 框架中常用的按钮控件,主要用于触发交互操作。

  • Push Button
    推按钮,也叫普通按钮,通常是一个矩形区域,上面显示的文本是该按钮的标签。当用户点击按钮时,会发出 clicked() 信号。
  • Tool Button
    工具按钮,通常是一个图形化的按钮,可以在图标和文本标签之间进行选择。默认情况下,工具按钮只包含图标,但是可以通过设置 toolButtonStyle 属性来更改其显示方式,比如可以显示文本标签或者在鼠标悬停时显示文本标签。
  • Radio Button
    单选按钮,通常用于多选一的场景,用户可以从多个选项中选择一个。通常情况下,单选按钮会通过与其他单选按钮的 group 联系在一起,保证同一时间只有一个单选按钮被选中。
  • Check Box
    复选框,通常用于多选的场景,用户可以从多个选项中选择多个。与单选按钮不同,复选框不需要分组,因为用户可以同时选中多个复选框。
  • Command Link Button
    命令链接按钮,通常用于表示执行一个重要操作或打开一个重要的对话框,这个按钮的文字通常使用一个动词短语,比如“保存”,“重命名”等等。命令链接按钮的外观会随平台的不同而不同。
  • Dialog Button Box
    对话框按钮盒子,通常用于对话框中放置一组按钮,比如“确定”,“取消”等等。这个控件提供了一套标准的按钮类型,可以方便地将这些按钮添加到对话框中,同时可以通过 signals 和 slots 进行与这些标准按钮的交互。

3、Push Button 按钮编程

3.1 程序完成后的执行结果

程序完成后的执行结果如下图:

ios pushViewController不生效的原因 push-button neanderthal_qt_02

按下黄色窗口按钮,窗口显示黄色,按下粉色按钮,窗口显示粉色。

3.2 生成项目

新建一个项目名称为为_qpushbutton

ios pushViewController不生效的原因 push-button neanderthal_qt_03

选择Widget基类,去掉Generate Form勾选:

ios pushViewController不生效的原因 push-button neanderthal_QT_04

QT通常使用QMainWindow作为主窗口。
QMainWindow是一个窗口风格的控件,通常会有一个窗口标题栏,并支持窗口大小调整、最大化、最小化等标准窗口管理操作。在主窗口的最中间是是一个central widget,提供主窗口的主要内容或用户交互接口,比如文本编辑器或者OpenGL视图等。QWidget通常用作窗口中的子控件或对话框等非窗口风格的控件。
如果在Qt应用程序中只需要一个窗口且不需要标准的窗口管理功能,则QWidget可以被用作主窗口。
在嵌入式应用中,由于触摸屏通常用作显示或控制,不涉及太多编辑工作,使用QWidget作为主窗口会更为适用。

  • 将两个配置好的Kits同时选上(后期我们会通过条件编译进行选择):

ios pushViewController不生效的原因 push-button neanderthal_Qt_05

- 项目生成的最初代码

ios pushViewController不生效的原因 push-button neanderthal_QT_06

3.3 完成代码编辑

3.3.1 修改项目文件 _qpushbutton.pro

1 	QT       += core gui
2 
3 	greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
4 
5 	CONFIG += c++11
6 
7 	# You can make your code fail to compile if it uses deprecated APIs.
8 	# In order to do so, uncomment the following line.
9 	#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
10
11	SOURCES += \
12		main.cpp \
13		widget.cpp
14
15	HEADERS += \
16		widget.h
17
18	# Default rules for deployment.
19	qnx: target.path = /tmp/$${TARGET}/bin
20	else: unix:!android: target.path = /opt/$${TARGET}/bin
21	!isEmpty(target.path): INSTALLS += target
22
23
24	# 根据使用的 Qt 版本设置编译条件
25	greaterThan(QT_MAJOR_VERSION, 4) {
26		# 如果使用的是 Qt 5 或者更新版本
27		message("使用的是 Qt 5版本")
28
29	} else {
30		# 如果使用的是 Qt 4 或者更早的版本
31		message("使用的是 Qt 4版本")
32		DEFINES += QT_ARM_PLATFORM
33		QMAKE_CXXFLAGS += -std=c++11
34		QMAKE_CXXFLAGS += -Wno-psabi -Wno-deprecated-declarations
35
36		LIBS += -lts
37
38	}

我们在系统生成的项目文件中使用条件编译增加目标为qt4-arm时的代码:

  • 第32行:定义预处理器宏 QT_ARM_PLATFORM,这个宏将被传递给编译器和链接器,用来在程序中做条件编译。
  • 第33行:由于最新版本的 Qt Creator 默认使用了 C++11 标准。所以在自动生成的代码中会使用 C++11 新增的关键字 nullptr,但是我们的编译器并不认识它,会导致编译失败。增加QMAKE_CXXFLAGS += -std=c++11就能修正这一错误。
    第34行:
    QMAKE_CXXFLAGS += -Wno-psabi -Wno-deprecated-declarations 可以帮助我们忽略掉我们不关心的警告。
    第35行:LIBS += -lts 指令用于链接触摸屏 tslib的库文件。

3.3.2 修改main.cpp

1 	#include "widget.h"
2 
3 	#include <QApplication>
4 
5 	#ifdef QT_ARM_PLATFORM
6 	#include <QTextCodec>
7 	#endif
8 
9 	int main(int argc, char *argv[])
10	{
11		QApplication a(argc, argv);
12
13	#ifdef QT_ARM_PLATFORM
14		//解决中文乱码
15		QTextCodec::setCodecForTr(QTextCodec::codecForName("GBK"));
16		QTextCodec::setCodecForTr(QTextCodec::codecForName("system"));    //若英文系统,则用GBK
17		QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
18		QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
19	#endif
20		Widget w;
21		w.show();
22		return a.exec();
23	}

QTextCodec是Qt中一个用于字符编解码的类,用于将文本字符串转换为不同字符集或编码方式的二进制数据,或将二进制数据解码为文本字符串。
为了解决当程序运行在arm架构系统时,中文显示文乱码问题,根据从.pro获得的宏QT_ARM_PLATFORM判断如果系统运行在arm架构,则执行:

  • 第6行:引入 QPushButton
  • 第8行:获取系统支持的编解码器,将GBK设置为translate文本编解码器。
  • 第9行:如果是英文系统,则也使用GBK编解码。
  • 第10行:设置当前系统环境的locale编码为UTF-8,这样在进行文本字符串操作时会自动地将其转换为UTF-8编码,从而使其和其他模块的字符串匹配。
  • 第11行:设置CStrings使用UTF-8编码格式,这样当我们在程序中使用常量字符串时也会自动地将其转换为UTF-8编码,以避免编码不一致的问题。

3.3.3 修改widget.h

1 	#ifndef WIDGET_H
2 	#define WIDGET_H
3 
4 	#include <QWidget>
5 	/* 引入 QPushButton 类 */
6 	#include <QPushButton>
7 	class Widget : public QWidget
8 	{
9 		Q_OBJECT
10	public:
11		Widget(QWidget *parent = nullptr);
12		~Widget();
13	private:
14		/* 声明一个 QPushButton 对象 pushButton1 */
15		QPushButton *pushButton1;
16		/* 声明一个 QPushButton 对象 pushButton2 */
17		QPushButton *pushButton2;
18	private slots:
19		/* 声明对象 pushButton1 的槽函数 */
20		void pushButton1_Clicked();
21		/* 声明对象 pushButton2 的槽函数 */
22		void pushButton2_Clicked();
23	};
24	#endif // WIDGET_H

第 6 行,引入 QPushButton 类。
第 15 行和 第17 行,声明两个 QPushButton 的对象。
第 20行和 第 22 行,声明两个 QPushButton 对象的槽函数。

3.3.4 修改widget.cpp

1 	#include "widget.h"
2 
3 	Widget::Widget(QWidget *parent)
4 		: QWidget(parent)
5 	{
6 		/* 设置宽高为 800×480,位置在 0, 0。(0, 0)代表原点,Qt 默认最左上角的点为原点 */
7 		this->setGeometry(0, 0, 800, 480);
8 
9 		/* 实例化两个按钮对象,并设置其显示文本为"黄色窗口"和"粉色窗口" */
10		pushButton1 = new QPushButton("黄色窗口", this);
11		pushButton2 = new QPushButton("粉色窗口", this);
12		
13		/* 设定两个 QPushButton 对象的位置 */
14		pushButton1->setGeometry(300,200,80,40);
15		pushButton2->setGeometry(400,200,80,40);
16
17		/* 信号槽连接 */
18		connect(pushButton1, SIGNAL(clicked()), this,  SLOT(pushButton1_Clicked()));
19		connect(pushButton2, SIGNAL(clicked()), this,  SLOT(pushButton2_Clicked()));
20	}
21
22	Widget::~Widget()
23	{
24	}
25
26	/* 槽函数的实现 */
27	void Widget::pushButton1_Clicked()
28	{
29		/* 设置主窗口的样式 1 */
30		this->setStyleSheet("Widget { background-color: rgba(255, 255, 0, 100%); }");
31	}
32
33	/* 槽函数的实现 */
34	void Widget::pushButton2_Clicked()
35	{
36		/* 设置主窗口的样式 2 */
37		this->setStyleSheet("Widget { background-color: rgba(255, 192, 203, 100%); }");
38	}

第 7 行,设置程序窗口的显示位置和显示大小,在我们使用的硬件里,窗口占满整个屏幕。
第10行 和 第11行,实际化 QPushButton 对象。在初始化的时候可以传入 QString 类型串,作为
按钮的显示文本。
第 14 行和第15行,设置按钮的大小和位置。
第 18 行和 19 行,连接两个 QPushButton 对象的信号与槽。
第27~31行,定义第一个槽函数pushButton1_Clicked()。
第34~38行,定义第二个槽函数pushButton2_Clicked()。
pushButton1_Clicked()pushButton2_Clicked()两个函数的功能是,当点击按钮时,窗口的背景颜色按照background-color 的 rgba 设置值, 发生相应的变化。

3.4 切换Kit,获得运行在不同系统中的运行的执行文件

点击窗口左边的Debug,可以选择编译运行在不同平台上的可执行文件,arm-v7为arm架构的设备,桌面则是当前ubuntu系统。

ios pushViewController不生效的原因 push-button neanderthal_开发语言_07

3.5 程序中用到的QT机制

3.4.1 信号(Signal)和槽(Slot)

信号(Signal)和槽(Slot)是Qt中重要的一种机制。它们的作用是在对象之间进行通信和交互,使得应用程序能够响应事件并实现特定的功能。Qt的信号和槽机制是一种基于事件的编程模型,可以实现对象之间的松耦合,使得事件的处理更为简单和灵活。
简单来说,信号是对象发出的一个通知或事件,而槽则是对象接收并响应这个通知或事件的函数。一个对象可以有多个信号和槽,而且它们之间可以相互连接,使得一个对象的信号能够触发另一个对象的槽,从而实现复杂的交互功能。
Qt中的信号和槽使用connect()函数进行连接。当某个对象的信号被触发时,与之相连的槽函数会被自动调用,从而实现事件的处理,我们上面的程序中,以pushButton1为例,实现代码如下:

connect(pushButton1, SIGNAL(clicked()), this,  SLOT(pushButton1_Clicked()));

pushButton1是一个QPushButton对象,点击它,会发出一个clicked()信号;
this是当前窗口对象,它定义了pushButton1_Clicked()的槽函数,用于响应clicked()信号;
connect函数将pushButton1的clicked()信号与窗口对象的pushButton1_Clicked()槽函数连接起来。
当用户点击pushButton1按钮,pushButton1_Clicked()槽函数就会被自动调用。

3.4.2 样式表

Qt提供了样式表(Style Sheet)机制,可以用于设置应用程序中控件的外观和布局。样式表是一种基于CSS语法的文本文件,通过设置不同的属性和值来改变控件的外观和行为。
下面一个是使用样式表来设置控件风格的例子:
QWidget{
background-color: white;
}
设置QWidget背景色为白色。

在我们的中,使用setStyleSheet()函数来将样式表应用到控件上。

this->setStyleSheet("Widget { background-color: rgba(255, 255, 0, 100%); }");

或是可以这样写:

this->setStyleSheet("background-color: yellow;");

总结

本例程为Push Button按钮编程。通过这个例子,初步了解QT的信号与槽、样式表等机制,此外,我们的调试环境配置了双架构Kits,使得编译调试可以在当前的ubuntu中进行,也可以重新编译后下载到目标arm设备中运行。