Qt是挪威一个团队开发的多平台C++图像用户界面应用程序框架。Qt是面向对象的框架,使用特殊的代码生成扩展。
Qt Creator是一个用于Qt开发的轻量级跨平台集成开发环境。支持跨平台开发。
1.QT的优势:
- 优良的跨平台特性,支持windows系列,linux,unix等操作系统及win7,win10,unix等平台。
- 面向对象,有良好的封装机制,模块化程度高,可重用性较好。
- 丰富的API,大量C++类,模板,开发文档等
2.QT内存管理
C++使用new和delete时,内存在堆中分配,需要自己手动通过delete释放,不然会内存泄漏,分配在堆上的对象会一直存活。
而Qt中,所有从QObject继承出来的子类定义的对象的内存管理都转移给了父对象。所以使用new在堆上分配内存,子对象可自dan动被父对象删除内存,即使你手动delete也不会引起二次删除。
对没有父对象的对象需要手动删除,不过一般放在栈区,注意Qt没有自动回收机制,这种对象的内存分配要注意。
3.Qt程序的一些补充说明
在创建一个 Qwidget 项目后,其项目文件 xxx.pro 中
QT +=core gui //指定使用类的模块
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = hello //目标文件名
TEMPLATE = app //编译方法
HEADERS += \ //头文件
widget.h
main.cpp文件
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv); //GUI事件处理对象
Widget w; //定义窗口类对象
w.show(); //显示窗口
return a.exec();//事件循环,内部为一个事件队列
}
界面或操作文件,如widget.cpp,因为学习Qt更注重实践,所以相关知识以注释的方式在代码中添入
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
cout<<"hello qt"<<endl; //C++打印方式
qDebug() << "hello QT"; //qt的打印
//this->setFixedSize(640,480);//将窗口设置为固定大小
this->setMinimumSize(480,480);//窗口的(尺寸)最小值,初始打开的即为最小值
this->setMaximumSize(1000,1000);//窗口的(尺寸)最大值
this->setWindowTitle("welcom qt");//窗口标题
this->setWindowIcon(QIcon("./icon.png"));//窗口图标,自己给文件路径
//pb1=new QPushButton(this);
//pb2=new QPushButton("ok",this);
//有布局则可省略this,因为按钮显示在布局上
pb1=new QPushButton("用户");//new的空间在qt不用手动销毁
//pb2=new QPushButton("打印");
pb2=new QPushButton(QIcon("./我的产品"),"打印");
//pb2->setFixedWidth(50);
#if 0
//水平布局
QHBoxLayout *hbox = new QHBoxLayout;
hbox->addWidget(pb1);
hbox->addWidget(pb2);
this->setLayout(hbox);//设置窗口布局
#endif
#if 0
//垂直布局
QVBoxLayout *vbox = new QVBoxLayout;
vbox->addWidget(pb1);
vbox->addWidget(pb2);
this->setLayout(vbox);//设置窗口布局
#endif
#if 1
//组合布局
le=new QLineEdit;
QHBoxLayout *hbox=new QHBoxLayout;
hbox->addWidget(pb1);
hbox->addWidget(le);
QVBoxLayout *vbox =new QVBoxLayout;
vbox->addLayout(hbox); //添加布局
vbox->addWidget(pb2); //添加控件
this->setLayout(vbox);//设置窗口布局
#endif
#if 0
//珊格布局
pb1->setText("1");
pb2->setText("2");
pb3 =new QPushButton("3");
QGridLayout *gbox =new QGridLayout;
gbox->addWidget(pb1,0,0,1,2);
gbox->addWidget(pb2,1,0,1,1);
gbox->addWidget(pb3,1,1,1,1);
setLayout(gbox);
#endif
//绑定信号与槽
//connect的参数:谁产生信号 信号 谁处理信号 槽函数
//connect(pb1,SIGNAL(clicked(bool)),this,SLOT(close()));
connect(pb1,SIGNAL(clicked(bool)),this,SLOT(set_clicked()));
connect(pb2,SIGNAL(clicked(bool)),this,SLOT(ok_clicked()));//自定义槽函数,如ok_clicked()且是this的成员函数
}
Widget::~Widget()
{
}
//自定义的槽函数,pb2按钮的
void Widget::ok_clicked()
{
QString str=le->text();//获取行编辑器的内容
qDebug()<<str;
}
void Widget::set_clicked()
{
QString str=pb1->text();//获取pb1按钮内容
le->setText(str);
//le->setText(QString::number(666));//将数值数据显示在行编辑器上
}
头文件widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QDebug> //qt界面调试
#include <QIcon> //图标类
#include <QPushButton> //按钮
#include <QHBoxLayout> //水平布局
#include <QVBoxLayout> //垂直布局
#include <QLineEdit> //行编辑器
#include <QGridLayout> //栅格布局
#include <iostream>
using namespace std;
class Widget : public QWidget
{
Q_OBJECT //自定义类时使用
public:
Widget(QWidget *parent = 0);
~Widget();
private slots: //槽函数的声明需要放在slots标签下,对于private权限可改,影响继承而已
void ok_clicked();
void set_clicked();
private:
QPushButton *pb1,*pb2,*pb3;
QLineEdit *le;//行编辑器
};
#endif // WIDGET_H
以上代码使用了一些控件,控件的详细讲解将在后面介绍
4.信号与槽机制
信号和槽机制是Qt的一个主要特征,是Qt与其他工具包最不相同的部分,通过反馈的方式动态地或松散地将事件和状态变化联系起来。
Qt的工作原理:事件驱动,信号和槽机制
回调是一个函数指针,当一个事件发生时被调用,任何函数都可以被安排为回调。但这种方式没有类型安全,且是直接调用。
而信号和槽的方式更加动态,更容易互连两个已存在的类。Qt采用信号和槽实现对象部件之间的通信。
1.信号
当信号被发射时,QT代码将回调与其相连接的槽函数。信号的声明放在头文件中,作为类的signals成员,只用声明,不用定义。
2.槽函数
槽函数是普通的C++成员函数,但访问权限有些不同。
三种权限:权限决定了谁能够与该槽函数相关联。
public slots
privat slots
protected slots
槽函数可以有返回值,也可没有。
3.连接
1、信号与槽函数关联: connect
一对一:
一个信号对应一个槽函数
一对多:
一个信号对应多个槽函数
多对一:
多个信号对应同一个槽函数
2、信号与信号关联:
sig1关联sig2时,当sig1产生时会自动触发sig2信号,但是sig2产生时不会触发sig1
3、解除关联:
disconnect
4、槽函数的参数:
槽函数的参数是由信号的参数传递,因此:
槽函数的参数个数一定是小于或等于信号的参数个数
当槽函数有参数时,参数类型一定与信号对应参数类型一致
5、信号的发射:
emit 信号
例子:
pb1 = new QPushButton("1");
pb2 = new QPushButton("2");
QHBoxLayout *hbox = new QHBoxLayout;
hbox->addWidget(pb1);
hbox->addWidget(pb2);
setLayout(hbox);
connect(pb1, SIGNAL(clicked(bool)), this, SLOT(display1()));
connect(pb2, SIGNAL(clicked(bool)), this, SLOT(display2()));
connect(pb1, SIGNAL(clicked(bool)), pb2, SIGNAL(clicked(bool)));