嵌入式项目的图形解决方案
- ucOS + us/GUI (STM32)
- Linux + QT
QT
https://download.qt.io/new_archive/qt/
教程:http://c.biancheng.net/view/3871.html
-
跨平台的C++ GUI(图形图像接口)应用程序开发架构。
- 可以在不同平台下运行(windows, linux, 嵌入式linux, android…)
-
面向对象,良好的封装机制,模块化程度高。提供了signals信号/slots槽 的安全类型来替代callback,简化各个元件之间的协同工作。
- 丰富的API,500个以上的C++类,还提供基于模板的collections, serialization, file, I/O device, directory management, date/time类,正则处理。
- 大量开发文档
- 集成开发工具, 包含一组类库,可以开发GUI程序,也可以开发非GUI程序。
- 应用:工业机器人、大型服务器开发、游戏领域、三维动画、嵌入式领域
跨平台的实现
- 基于不同的平台(window\linux\嵌入式Linux)有不同的QT类库,功能一致。但所有平台QT类库对上层(QT类库应用层接口)提供同样的访问接口。=》基于QT类开发跨平台的GUI 应用
qmake vs cmake
base class: QWidget\QMainWindow\QDialog
- QWidget类是所有用户界面对象的基类。
- QMainWindow 类提供一个有菜单条、锚接窗口(例如工具条)和一个状态条的主应用程序窗口。
- QDialog类是对话框窗口的基类。对话框窗口是主要用于短期任务以及和用户进行简要通讯的顶级窗口。
kits
Hello World
创建项目
hello.pro项目文件
QT += core gui //指定QT调用到的模块, 网络编程时可能需要加入network网络模块
TARGET = hello // makefile要用的,指定应用程序名字
TEMPLATE = app // 应用程序类型
SOURCES += ... // 包含哪些.cpp源文件
HEADERS += ... // 头文件
FORMS += ... // 窗体文件
.ui 设计
- 编译生成ui_hellowidget.h文件(build-hello-Desktop_Qt_5_11_3_MinGW_32bit-Debug生成文件中的)
-
生成文件ui_hellowidget.h
- 声明了一个Ui_MainWindow类:描述图形界面
BtnShowHello = new QPushButton(centralWidget);
BtnShowHello->setObjectName(QStringLiteral("BtnShowHello")); // 设置名字
BtnShowHello->setGeometry(QRect(240, 70, 141, 51)); // 设置大小
- 声明一个Ui的命名空间
- 声明MainWindow(HelloWidget)类
.h 槽函数声明
public slots:
//槽函数声明,与按钮对象相关联
void BtnHelloSlot(void); // 界面类MainWindow的成员函数
.cpp 槽函数定义
void MainWindow::BtnHelloSlot(void) //实现类中的槽函数
{
ui->LabelHello->setText("Hello World"); // 为ui中的LabelHello设置文本
}
.cpp 信号与槽函数关联
connect(ui->BtnShowHello, SIGNAL(clicked(bool)), this, SLOT(BtnHelloSlot())); //ui->BtnShowHello的点击信号与当前对象的BtnHelloSlot槽函数关联
完整代码解析
mainwindow.h(hellowidget.h) , mainwindow.cpp (hellowidget.cpp)窗体类文件
- 文件
- hellowidget.h =》类的头文件,声明类
- hellowidget.cpp =》 类的实现文件,实现了类的成员函数
- mainwindow(hellowidget)类:主界面窗体类,继承自Widget类。
// hellowidget.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow> // 1. 头文件
// 2. 声明命名空间ui
namespace Ui {
class MainWindow;
}
// 3. 声明一个HelloWidget类
// 3.1 MainWindow是由QMainWindow类采用公共继承的方式继承来的(与Ui中MainWindow不同,命名空间不一样)
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr); // 3.2 构造函数(包含一个指向parent的指针)
~MainWindow(); // 3.3 析构函数
public slots:
// 3.3 槽函数声明,与按钮对象相关联
void BtnHelloSlot(void); // 界面类MainWindow的成员函数
private:
// 3.4 类的私有成员, MainWindow类型(ui_hellowidget.h中Ui的类)
// MainWindow类由ui_hellowidget.h中Ui_MainWindow类继承来的
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
// hellowidget.cpp
#include "hellowidget.h"
#include "ui_hellowidget.h"
/*
* 类的实现文件
*/
// 2. 构造函数
// 派生类的构造函数需要调用基类的构造函数QMainWindow(parent)
// 参数列表ui(new Ui::MainWindow)
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow) // 相当于ui = new Ui::MainWindow, new出一个对象来初始化ui
{
// 2.1 创建主窗体界面(ui_hellowidget.h中Ui_MainWindow类函数)
ui->setupUi(this);
// 2.2 调用connect函数 将btn点击信号与当前对象的BtnShowHelloSlot槽函数关联
connect(ui->BtnShowHello, SIGNAL(clicked(bool)), this, SLOT(BtnHelloSlot()));
}
// 3. 析构函数:清除类资源
MainWindow::~MainWindow()
{
delete ui;
}
// 1. 实现类中的槽函数
void MainWindow::BtnHelloSlot(void)
{
ui->LabelHello->setText("Hello World"); //设置文本
}
main.cpp
- main函数:定义应用程序对象和主窗体对象,显示主窗体,运行应用程序。
#include "hellowidget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv); // 1. 定义应用程序类QApplication
MainWindow w; // 2.定义主窗体类MainWindow(hellowidget.h中)的对象
w.show(); // 3.显示主窗体
return a.exec(); // 4. 运行应用程序,需要把主窗体关掉才返回
}
事件处理机制
Qt程序是事件驱动的,程序的每个动作都是由幕后某个事件所触发,Qt事件的发生和处理成为程序运行的主线,存在于程序的整个生命周期。
当调用QApplication::exec()时,就进入了事件循环,应用程序就开始等待并处理事件。
-
键盘事件:按键按下和松开
- 鼠标事件
- 拖放事件
- 滚轮事件
-
绘屏事件:重绘屏幕的某些部分
- 定时事件
QDebug调试
输出结果在“3应用程序输出”中查看
# include<QDebug>
int conter = 0;
// 方法1
qDebug("connect ok %d\n", conter);
// 方法二
qDebug<<"hello world"<<endl;
信号和槽
- Qt核心机制,应用于对象之间的通信
- 是Qt的核心特征,也是Qt差别于其他工具包的重要地方。
- 当一个对象的状态发生改变时,通过信号的方式通知其他对象(不指定发给哪个对象),其他对象通过执行相应的槽函数来响应该信号。
signals信号
class cName
{
signals:
// 信号定义
void mySinal(); // 1
void mySignalParam(int x, int y); // 2 可以带参数,但不是函数定义
}
slots槽函数(类的成员函数)
- 可以像调用类的成员函数一样来调用槽函数
- 与普通类的成员函数区别:可以跟信号建立起关联
class cName
{
public slots:
// 公有插槽: 可以跟任何信号关联
void mySlot();
void mySlotParam(int x, int y);
protected slots:
// 保护插槽:只能跟该类及其子类信号关联
private slots:
// 私有插槽:只能跟该类本身的信号关联
}
PS: 如果一个信号跟多个槽函数建立起了关联,一旦信号发生,与它建立关联的槽函数都会执行,谁先谁后不能确定。
使用 emit
- signal一般在事件的处理函数中发出,利用emit发射信号。
- 如果一个类要使用信号与插槽机制,它就必须是从QObject或者其子类继承,而且在类的定义中必须加上Q_OBJECT宏。
class MainWindow : public QMainWindow
{
Q_OBJECT // 宏定义
...
}
- 信号的参数是实参,槽函数形参的实参从信号传过来 =》确保信号的参数类型与参函数形参类型一致
connect()信号与槽函数关联
disconnect()取消信号与槽函数之间的关联
- 不常用,对象被删除后自动取消这个对象所包含的所有连接
实例
// .h
class MainWindow : public QMainWindow
{
...
public slots:
void BtnHelloSlot(void);
void mysignalSlot(void); // 4 槽函数
signals:
void mysignal(); // 4 自定义信号
...
}
// .cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->BtnShowHello, SIGNAL(clicked(bool)), this, SLOT(BtnHelloSlot()));
connect(this, SIGNAL(mysignal()), this, SLOT(mysignalSlot())); // 4 关联
}
// 4 槽函数
void MainWindow::mysignalSlot(void)
{
ui->lineEdit->setText("Hello World");
}
void MainWindow::BtnHelloSlot(void)
{
ui->LabelHello->setText("Hello World");
emit mysignal(); // 4.发射信号
}