QT应用开发基础
Posted 行稳方能走远
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了QT应用开发基础相关的知识,希望对你有一定的参考价值。
目录
前言
在嵌入式上,我们少不了界面的开发,一种是用安卓,一种是用 QT,那么安卓对 CPU 的性能要求比较高,不是所有的 CPU 都可以运行,但是 QT 对 CPU 要求不高,甚至可以在单片机上来运行,而且 QT 是一个非常优秀的跨平台工具,一套代码我们可以在多个平台上来运行,比如 Windows,android,Linux 等,换一套编译器即可更换不同的平台。所以非常的方便和有趣。因为QT 开发需要 C++基础,不过不用担心,QT 上用的 C++并不多,大部分都是C语言的知识。
Windows上搭建开发环境
Qtcreator 下载地址:http://download.qt.io/new_archive/qt/5.11/,进入选择版本号界面,本教程使用的是5.11.1,也推荐读者选择此版本。进入如图 界面后,选择安装包,我们在windows 下学习Qt,所以选择qt-opensource-windows-x86-5.11.1.exe,点击即可下载。
下载后右键点击exe 文件,选择以管理员身份运行。注册账号,点击下一步(或next),选择安装路径。选择下一步,勾选需要用到的组件,本阶段教程需要勾选以下七个选项:
选择完后一直点下一步,安装完成后如图
C++基础
什么是C++
c++是 c 语言的升级版,在 c 的基础上增加了很多功能。是一种高级语言,常见后缀:cpp,c++,cc 等。
g++编译:gcc 是一个通用命令,它会根据不同的参数调用不同的编译器或链接器,GCC 为了让操作简单推出 g++命令用来编译 C++。
C++命名空间:中大型软件项目在多人合作开发时会出现变量或函数的命名冲突,C++ 引入了命名空间来解决变量重复定义。声明命名空间 std:using namespace std,后续如果有未指定命名空间的符号,那么默认使用 std,cin、cout ,endl 都位于命名空间 std。
#include <iostream>
namespace A{
int num = 1;
}
namespace B{
int num = 2;
}
int main(int argc, const char *argv[])
{
int m = A::num;
std::cout << m << std::endl;
m = B::num;
std::cout << m << std::endl;
return 0;
}
什么是面向对象,什么又是面向过程
c 语言就是面向过程的,c++就是面向对象的,面向对象特点:封装,继承,多态。
举例:a+b
直接计算 a+b 就是面向过程。
面向对象就是给 a+b 穿上了一层衣服。不是直接计算 a+b。
c++的灵魂:c++的类
类大家可以把他看成c 语言结构体的升级版。类的成员不仅可以是变量,也可以是函数,类可以看做
是一种数据类型,这种数据类型是一个包含成员变量和成员函数的集合。比如:
class student
{
public:
//成员函数
char name[64];
int age;
//成员函数
void do(){
Cout << “function” <<endl;
}
};
对象:类的实例化
直接定义:
student my; // student 就是类my 就是对象
在堆里面定义:
student *my = new student;
删除对象:
delete my; 目的是释放堆里面的内存
my = NULL; 变成空指针,杜绝成为野指针。
怎么访问类的成员
int main(){
student my;
student *my1 = new student;
my.age = 18;
my1->age =19;
cout << my.age << endl;
cout << my1->age << endl;
}
访问方法和C 语言结构体是一样的,普通变量通过. 指针通过->
类的函数成员
因为类里面的成员不仅可以是变量,也可以是函数。
第一步:在类里面声明
第二步:实现这个函数。我们可以直接在类里面写,也可以写在类的外面。
直接写在类的里面
class student
{
public:
char name[64];
int age;
void test(){
cout << 123 << endl;
};
};
写到类的外面
class student
{
public:
char name[64];
int age;
void test();
};
void student::test(){ //student:表示属于这个类里面的函数,不加的话会被识别成普通函数。
cout << 123 << endl;
};
};
访问函数和访问变量是一样的。
类的访问修饰符
类的访问修饰符就是对类的成员进行权限管理。
public:表示函数和变量是公开的,任何人都可以访问。
private:表示函数和变量只能在自己的类里面自己访问自己,不能通过对象来访问。
能不能强行访问?可以的,娆一个弯,通过访问函数(函数里面携带变量的值)间接访问变量
protected:表示函数和变量只能在自己的类里面自己访问自己,但是可以被派生类来访问的。
函数的重载
类函数的重载特性就是说我们可以在类里面定义同名的函数,但是参数不同的函数。
class student
{
public:
char name[64];
int age;
void test();
void test(int a);
private:
int haha;
};
重载函数在调用的时候,会根据参数的类型,然后去匹配相应的函数进行调用。
构造函数和析构函数
析构函数:假如我们定义了析构函数,当对象被删除或者生命周期结束的时候,就会触发析构函数。
构造函数:假如我们定义了构造函数,对象创建的时候就会触发这个构造函数(和析构函数正好相反)。
我们要怎么定义析构函数和构造函数?
1.析构函数和构造函数的名字必须和类名一模一样。
2.析构函数要在前面加上一个~
举例:
class student
{
public:
student();//构造函数 对象被创建的时候触发
~student();//析构函数 main函数return 0后触发析构函数
char name[64];
int age;
void test();
void test(int a);
private:
int haha;
};
student::student(){
cout << "hello" << endl;
}
student::~student(){
cout << "bye" << endl;
}
构造函数是可以被重载的。
析构函数不能被重载。
类的继承
类的继承允许我们在新的类里面继承父类的public 还有protected 部分,private 是不能被继承的。
当我们觉得这个类不好的时候,可以使用类的继承,添加我们需要的功能。
格式:
class 儿子:public 爸爸{
public:
........
Protected:
}
例子:
class mystudent:public student
{
public:
int grade;
};
如何在子类里面去访问父类的成员?
也是通过.和->来访问的。
虚函数和纯虚函数
虚函数:有实际定义的,允许派生类对他进行覆盖式的替换(父类内容被子类替换),virtual 来修饰。
纯虚函数:没有实际定义的虚函数就是纯虚函数。
举例:
virtual void test(); //虚函数
virtual void testa(){} //纯虚函数,里面没有任何代码
怎么定义一个虚函数?
用virtual 来修饰,虚函数是用在类的继承上的。
虚函数的优点?
可以预留接口,实现分工合作。像JAVA里面的重写。
制作一个简单的QT界面
qt 的移植性非常的强。一套代码我们不用改太多,直接通用所有的平台。
不久的将来,qt 会被用到MCU 上,学习QT 还是非常有意义的。
创建工程
步骤一:
步骤二:
填写工程名字,不要有中文路径:
步骤三:填写类名:
创建成功后如下图
工程目录下的.pro 工程文件分析:
点击forms,然后双击ui 文件,就可以进入ui 编辑器。
ui 编辑器面板介绍:
UI界面制作
信号和槽
信号就是指控件发出的特定的信号。槽就是槽函数的意思,信号和槽都位于类中,不是C++标准代码。我们可以把槽函数绑定在某一个控件的信号上。当需要调用外部函数时,发送一个信号,此时与该信号相关联的槽便会被调用,槽其实就是一个函数,槽与信号的关联要由程序员来完成,关联方法有自动关联和手动关联。
自动关联
使用Qt 信号和槽的自动关联,可加快开发速度,一般用于同一个窗体之间的控件关联,槽函数格式非常
关键,格式为:
void on_<窗口部件名称>_<信号名称>();
自动关联步骤:
步骤一:手动选择相应的控件,然后右键->转到槽。
选择信号类型:
自动关联会在.h 文件声明槽函数。槽函数只能声明到private slots 或者public slots 下面。按住Ctrl+鼠标左键,跳转到.cpp 文件对应的函数功能实现部分。填写功能代码,我们在槽函数内用qDebug 打印信息。
保存,点击构建,运行:
每次点击,按钮都会发信号,对应的槽函数就会执行,结果如图:
手动关联
信号和槽机制是QT 的核心机制,要精通QT 编程就必须对信号和槽有所了解。信号和槽是一种高级接口,应用于对象之间的通信,它是QT 的核心特性,也是QT 区别于其它工具包的重要地方。此外如果遇到不懂的函数或类,可以先选中,然后按F1 键,即可查看介绍。
虽然Qt 有自动关联功能,但涉及到多个窗体和复杂事件的时候,只能使用手动关联,手动关联使用connect 这个函数。
connect(const QObject *sender, const char *signal,const QObject *receiver, const char *member,Qt::ConnectionType = Qt::AutoConnection);
通常只传递前四个参数,参数含义:
sender:发送对象;
singal:发送对象里面的一个信号,格式一般为SIGNAL(信号);
receiver:接收对象;
member:接收对象里面的槽函数,格式一般为SLOT(信号)。
ConnectionType:设置信号和槽的同步异步,一般使用默认值Qt::AutoConnection,可不填。
connect(A,SIGNAL(B),C,SLOT(D));
当对象A 发出B 信号时候,就
会触发对象C 的槽函数D
signals 是QT 的关键字,而非C/C++ 的。signals 关键字指出进入了信号声明区,随后即可声明自己
的信号。
slots 槽是普通的C++ 成员函数,当与其关联的信号被发射时,这个槽函数就会被调用。槽函数有
的参数个数和类型,在对应的信号函数中必须一一对应,即信号函数的参数个数必须多于或等于槽函数的
个数。
emit Qt 定义的一个宏,作用是发射信号,与此信号关联的槽函数就会被调用。
例程:我们在widget.h 中自定义一个信号和一个槽函数
并在widget.cpp 实现槽函数:
然后在widget.cpp 中绑定信号和槽:
在widget.ui 中创建按钮,并转到槽,自动关联的槽函数如图
发射信号
这样,点击按钮,就会发射自定义的信号my_Signal(),与my_Signal()相关联的this 对象槽函数my_Solt就会被调用,槽函数就会输出打印信息,如图
部分核心代码如下:
Widget.h:
class student
{
public:
student();
~student();
char name[64];
int age;
void test();
void test(int a);
#include <QWidget>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
signals:
void my_Signal(void); //自定义的信号
private slots:
void on_pushButton_clicked();
void my_Solt(void); //自定义的槽函数
private:
Ui::Widget *ui;
};
Widget.cpp:
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
connect(this,SIGNAL(my_Signal()),this,SLOT(my_Solt()));
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_clicked()
{
emit my_Signal();
}
void Widget::my_Solt(void)
{
qDebug("按下");
}
给界面添加图片
添加资源
选中项目名称,右键单击—>选择添加新文件
在弹出窗口中选择Qt—>Qt Resource File ,选择Choose
填写写资源名称,
例如填写picture 后,在工程下的Resources 会出现picture.qrc 文件,成功后如图。
双击picture.qrc,点击“添加前缀”。
指定路径,这里笔者填的“/”此路径可根据需要自定义:
添加图片
我们首先将要添加的图片复制到工程目录下。
右击picture.qrc,选择Open With -> 资源编辑器,出现资源管理界面,点击下面的添加->添加前缀,
下方前缀栏填写的是“/ ”,这个路径可以根据需要自定义,然后保存。
再次点击“添加”,点击“添加文件”,
选中图片,点击“打开”,进入资源编辑器
在资源编辑器中会看到添加的图片,然后保存。
以此点开Resources 下的各个文件夹,即可看到添加的图片,此时图片已经添加到工程。
Label 添加图片
在ui 文件添加QLabel 组件,右击->选择改变样式表,
弹出对话框,选择添加资源->border image,
选择要添加的图片,如图
点击OK,apply,OK,即可完成添加,如图
界面布局
水平布局
Horizontal Layout 水平方向布局,组件自动在水平方向上分布
使用时先选中组件,然后点击水平布局即可完成,可看到组件变为水平排列。如图
垂直布局
Vertical Layout 垂直方向布局,组件自动在垂直方向上分布,操作方法和水平布局一致,在布局之后组件垂直排列。
我们点击打破布局按钮,重新选择要布局的组件,然后点击垂直布局按钮,如图
栅格布局
Grid Layout 网格状布局,网状布局大小改变时,每个网格的大小都改变
我们发现布局之后各个组件都是紧挨着的,这时候可以用“弹簧”控件来控制组件位置。
Horizontal Spacer 一个用于水平分隔的空格
完成后如图
Vertical Spacer 一个用于垂直分隔的空格,拖拽组件如图
选中点击垂直布局,完成后如图
界面切换
本节通过实验介绍通过创建窗口对象的方式实现界面切换:
步骤一:
在主界面ui 文件添加pushButton 按钮,
然后新建一个窗口,工程下创建新的Qt 设计师界面类,如图
我们选择Widget,用户可以根据需要选择,然后输入类名windowRun。
创建完成后如图
步骤二:关联ui 界面的pushButton 的clicked()信号和槽函数runSolt(),部分代码:
{
ui->setupUi(this);
connect(ui->pushButton,SIGNAL(clicked()),SLOT(runSlot()));//关联信号槽
}
步骤三:创建windowRun 类对象win,设置大小,显示。
void Example::runSlot(void)
{
qDebug ("Run slots");
//显示新窗口
win = new windowRun();
//设置win 窗口尺寸与此窗口尺寸相同
win->setGeometry(this->geometry());
//显示
win->show();//win->close();关闭
}
运行程序后,点击按钮后即可跳转到第二个界面。
以上是关于QT应用开发基础的主要内容,如果未能解决你的问题,请参考以下文章