day39-QT

day39-QT

一、QT简介

  QT是一个跨平台的应用程序开发框架,它可以用来创建图形用户界面(GUI)和非GUI应用程序。QT的特点是使用C++作为编程语言,提供了一套丰富的类库和工具,以及一种元对象系统(MOC),可以实现信号和槽机制,以及动态类型转换等功能。

  QT的优势在于它提供了一致的编程接口和体验,无论是在不同的操作系统或者不同的设备上,都可以使用相同的代码和工具来创建应用程序。QT还提供了许多高级的功能和组件,例如网络、数据库、多媒体、XML、OpenGL等。此外,QT还支持多种编程语言,除了C++之外,还有Python、Ruby、Java等。QT还有一个活跃的社区和开源许可,使得开发者可以方便地获取技术支持和资源。




二、QT项目结构

一般来说,一个QT项目由以下几个部分组成:

  • .pro文件:这是一个项目配置文件,它定义了项目的基本信息,如项目名称、版本、目标平台、源文件列表、头文件列表、资源文件列表、依赖库等。.pro文件是由qmake工具解析的,qmake可以根据.pro文件生成相应平台的构建文件,如Makefile或Visual Studio工程文件。
  • 源文件:这是项目的核心部分,它包含了项目的业务逻辑和算法实现,通常以.cpp为扩展名。源文件中可以包含QT的宏和关键字,如Q_OBJECT、signals、slots等,这些宏和关键字可以被moc工具识别和处理,moc可以根据源文件生成元对象代码,这些代码实现了QT的对象模型和信号槽机制。
  • 头文件:这是项目的接口部分,它声明了项目中使用的类、函数、变量等,通常以.h为扩展名。头文件中也可以包含QT的宏和关键字,如Q_OBJECT、signals、slots等,这些宏和关键字同样可以被moc工具识别和处理,moc可以根据头文件生成元对象代码。
  • 资源文件:这是项目的外观部分,它包含了项目中使用的图标、图片、音频、视频等非代码资源,通常以.qrc为扩展名。资源文件是由rcc工具解析的,rcc可以根据资源文件生成二进制资源代码,这些代码可以被嵌入到可执行文件中,或者作为外部文件分发。
  • 界面文件:这是项目的视觉部分,它定义了项目中使用的窗口、控件、布局等图形用户界面元素,通常以.ui为扩展名。界面文件是由uic工具解析的,uic可以根据界面文件生成界面代码,这些代码可以被包含到源文件中,或者作为单独的头文件使用。

通常创建的qt项目工程里有如下文件:

pro:指导生成makefile
widget.h:窗体类的定义
widget.cpp:类中成员函数
main.cpp:主函数 功能: 定义窗体对象 显示窗体 进入事件循环
widget.ui(xml): ui文件 uic工具将ui文件转换成c++代码 -> ui_widget.h




三、QT函数结构

3.1 main.cpp

main.cpp 是主函数文件,内部主要包含应用程序的入口函数,也就是 main() 函数。Qt 界面程序中的 main() 函数也有固定的格式:

1
2
3
4
5
6
7
8
9
int main(int argc, char *argv[])
{
QApplication a(argc, argv);//事件循环对象
//函数主体
widget w;//窗体对象,调用构造函数
w.show();//显示界面
//~函数主体
return a.exec();//事件循环
}

其中a.exec的功能如下:

1
2
3
4
5
6
while(1){
1.阻塞休眠等待事件发生
2.当事件发生后通过事件处理器处理事件(虚函数)
a.标准事件:事件处理器直接处理
b.非标准事件:事件处理器不知道怎么处理->emit信号 用户:关联信号与槽函数
}

3.2 widget.h

widget.h是界面的头文件,里面主要包含了widget的命名空间,基类QWidget和widget结构体。
下面是一般的widget格式:

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
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

//名字空间
namespace Ui {
class Widget;//声明
}

class Widget : public QWidget //界面类
{
Q_OBJECT //支持元对象编译器moc,即支持信号与槽

public:
explicit Widget(QWidget *parent = 0);//构造函数
~Widget();//析构函数

signals://自定义信号
void MySignal(QString);
private slots://槽函数
void on_btnClose_clicked();
void on_btnInsert_clicked();
void setTitle();

void on_btnWin_clicked();
void MySlot(QString);

private:
Ui::Widget *ui;//对象指针
};

#endif // WIDGET_H



注:如果要用到ui编辑则需要把widget声明在ui里,并且在ui里面的拖动的对象都要通过 ui->对象名 来调用

3.3 widget.cpp

widget.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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include "widget.h"
#include "ui_widget.h" //uic工具在编译时将widget.ui转换成c++代码
#include <QDebug>

Widget::Widget(QWidget *parent) : //构造函数的定义
QWidget(parent),//给基类的构造函数传递实参:parent
ui(new Ui::Widget) //ui = new Ui::Widget
{
ui->setupUi(this);//界面布局

connect(ui->btnTitle,SIGNAL(clicked(bool)),this,SLOT(setTitle()));//关联信号与槽 btnTitle -> clicked() -> Widget ->setTitle()
connect(this,SIGNAL(MySignal(QString)),this,SLOT(MySlot(QString)));//关联自定义信号和自定义槽函数

ui->lineEdit->setText("aaaaaaaaaa");//设置文本
qDebug() << ui->lineEdit->text();//获取文本

qDebug() << "Widget";//跟踪打印
}

Widget::~Widget()//析构函数的定义
{
delete ui;
}

//1.信号与槽关联: 右键组件 -> 转到槽 -> 信号
//适合: 标准信号
void Widget::on_btnClose_clicked()//btnClose -> clicked 信号 -> widget -> on_btnClose_clicked()函数
{
qDebug() << "on_btnClose_clicked。。。。。";//跟踪打印
this->close();//关窗口
}

//2.信号与槽关联: 通过命名规则关联,其实和第一种本质一样
void Widget::on_btnInsert_clicked()//命名规则:on_对象指针名_信号名
{
static int i = 0;

QString str;
str.sprintf("i=%d",++i);

ui->btnInsert->setText(str);

}

//3.信号与槽关联: 通过 +/-关联
//适合:信号和槽都是标准的

//4.通用的信号与槽函数的关联方式:
//connect
void Widget::setTitle()
{
this->setWindowTitle("MyWin");//修改窗体标题
}

void Widget::on_btnWin_clicked()
{
static int i = 0;

QString str;
str.sprintf("i=%d",++i);

ui->btnWin->setText(str);

//emit 自定义信号(str) -> 自定义槽函数 -> 显示为窗口标题
emit MySignal(str);//触发自定义信号
}

void Widget::MySlot(QString msg)
{

this->setWindowTitle(msg);

}

自己设置的信号要用emit触发。

四、QT内存管理

  • 自动存储管理:Qt中的大多数对象是使用自动存储管理的,这意味着它们的内存管理是由C++的自动变量和栈来处理的。当对象超出其作用域时,它们的内存会自动释放。

  • 动态存储管理:有时候需要在堆上分配对象,并手动管理它们的内存。Qt提供了两个主要的机制来进行动态内存管理:new 和 delete 运算符。可以使用 new 在堆上分配一个对象,并使用 delete 来释放它。注意,在使用 new 创建对象后,必须手动调用 delete 来释放它,以避免内存泄漏。另外,Qt还提供了 deleteLater() 函数,可以在稍后的时间点安全地删除对象。

  • 父子关系:Qt中的对象可以通过指定父对象来建立层次关系。当父对象被销毁时,它会自动销毁其所有的子对象。这种机制简化了内存管理,因为你只需要删除父对象,而不需要手动删除所有的子对象。

  • 智能指针:Qt还提供了一些智能指针类,如 QSharedPointer 和 QScopedPointer,用于帮助管理对象的生命周期。这些智能指针类能够自动跟踪对象的引用计数,并在不再需要时自动释放对象。




五、QT信号与槽简介

  Qt信号与槽是一种对象间通信的机制,可以让一个对象在发生某种事件时,通知另一个对象执行相应的操作。信号与槽机制是Qt的核心特性,也是Qt与其他框架最大的不同之处。

  信号是由对象发出的,表示某种状态的改变或者用户的操作。槽是用来响应信号的函数,可以是任何能和信号关联的成员函数或者普通函数。信号和槽可以通过QObject::connect()函数进行连接,指定发送对象、发送的信号、接收对象和接收的槽。例如:

1
2
//连接QPushButton的clicked信号和QLabel的setText槽
connect(button, SIGNAL(clicked()), label, SLOT(setText("Hello World")));

信号和槽有以下特点:

  • 信号和槽可以包含任意数量和类型的参数,只要参数类型可以进行隐式转换(类型匹配,信号参数的个数大于等于槽函数参数个数)或者注册到元对象系统。
  • 信号和槽必须使用void关键字声明,不能有返回值。
  • 信号和槽可以使用public、protected或者private修饰符,但是一般建议使用public或者protected。
  • 信号和槽可以使用Q_OBJECT宏声明在任何继承自QObject的类中,也可以使用Q_SIGNALS和Q_SLOTS宏声明在任何类中。
  • 一个信号可以连接到多个槽,一个槽也可以连接到多个信号。当信号发出时,连接到它的所有槽都会按照连接顺序依次执行。
  • 一个信号可以连接到另一个信号,这样当第一个信号发出时,会自动触发第二个信号。
  • 一个对象可以断开和另一个对象的所有连接,也可以断开特定的连接。断开连接可以使用QObject::disconnect()函数实现。

信号与槽相连接的几种方法:

  1. 右键组件->转到槽->选择信号->确定(命名规则:on_对象指针名_信号名)
  2. 直接命名方式
  3. +/-
  4. connect(发送信号的对象,信号,接收信号的对象,槽函数)
Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2020-2024 nakano-mahiro
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信