QT程序结构
程序特点
- 跟普通程序一样,头文件,源文件,工程文件
.pro
头文件特点
QT
系统头文件没有.h
- 头文件和类名一样
- 命名
Q
开头,前两个字母大写
工程文件
.Pro
的相关介绍
# 模块
QT += core gui
# 高于4版本添加本句内容,增加兼容
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
# 生成程序的名称
TARGET = my_first
# 指定Makefile生成的类型 app lib···
TEMPLATE = app
#警告信息
DEFINES += QT_DEPRECATED_WARNINGS
# 源文件
SOURCES += \
main.cpp \
mywidget.cpp
# 头文件
HEADERS += \
mywidget.h
# 增加对C++11的支持
CONFIG += C++11
- 特点
一个程序有多个对象时,默认情况下各个对象(窗口)是相互独立的,只有指定父类情况下,对象间才产生依赖关系,例如想在窗口对象上,建立一个按钮对象,那么按钮对象的父对象应该被设置为窗口对象。依赖关系确定只要父对象显示,那么子对象就会显示出来,子对象可以不必调用自身显示函数。
#include<QPushbutton>
int main(int argc,char **argv)
{
QApplication a(argc,argv);
QWidget w;
w.setWindowTitle("李京京");
QPushButton b;
b.setParent(&w);
b.setText("张超");
b.move(100,100);
QPushButton b1(&w);
b1.setText("李京京");
b1.move(200,100);
/*
*如果不指定父对象,对象和对象(窗口和窗口没有关系),独立
*a指定b为他的对象,a放在b的上面
*指定父对象有两种方式:
* 1)setParent
* 2)通过构造函数传参
*指定父对象,只要父对象显示,上面的子对象自动显示(不必在调用子对象显示函数)
*/
w.show();
return a.exec();
}
- 窗口对象
窗口或者其它可视对象创建以后,默认是隐藏的,只有调用显示函数时才会显示,编译运行程序时,如果没有调用显示函数,虽然没有看到任何东西,但程序已经在运行了,默认等不到用户处理它就会一直运行,我们可以通过任务管理器将它杀掉,或者通过IDE
停止按钮将程序结束运行。
信号与槽
信号连接函数
connect
(发出信号的对象地址,信号及所在类的地址,接收信号对象的地址,接受者的处理函数(槽函数)地址)
自定义信号
需要signals
:关键字修饰,信号形式类似函数声明,只声明不填充信号发射用emit
关键字修饰,槽函数与信号类型需要一致,无返回值,有无参数需要与信号形式保持一致。
信号重载
信号同名,不同参数时产生信号重载,connect
函数不能区分信号类型而产生错误,需要用函数指针来进行区分,最好不要用QT4
方式。QT4
方式虽然简单编译阶段不能检测信号是否正确,只有在运行时才能检测到错误与否,对于大型软件项目,此类方法并不好
//定义两个重载信号
signals:
void mysignal();
void mysignal(int,QString);
//定义信号发射
void SubWidget::myslot2()
{
emit mysignal();
emit mysignal(100,"1234");
}
//利用函数指针区分重载信号,避免二义性的产生
//函数指针需要添加定义域
//调用函数指针时直接调用即可
void (SubWidget::*funcSignal1)()=&SubWidget::mysignal;
void (SubWidget::*funcSignal2)(int,QString)=&SubWidget::mysignal;
connect(&w2,funcSignal1,this,&MainWidget::myslot3);
connect(&w2,funcSignal2,this,&MainWidget::myslot4);
Lambda函数
自定义槽函数需要声明、填充很麻烦,可以采用lambda
函数,直接将槽函数函数体写在信号与槽的函数内部Lambda
函数(匿名函数)是C++11
以后添加的新特性,我们可以利用Lambda
函数,代替槽函数,避免了槽函数声明构造等,增加代码效率,直接将槽函数写在函数体内部,使用时需要在工程文件里面添加CONFIG += C++11
connect(&w2,&SubWidget::mysignal,this,&MainWidget::myslot3);
void MainWidget::myslot3()
{
this->show();
w2.hide();
}
//利用匿名函数,直接将函数体写在连接函数内部比上面的写法要简洁
//【】中=代表将局部变量或者类中成员对象以值的方式传入函数体
//默认传入参数属性是只读属性,若想改变参数的值需要加mutable关键字[=]()mutable
connect(&w2,&SubWidget::mysignal,[=]()
{
this->show();
w2.hide();
}
);
实现主副窗口切换的QT程序(入门程序)
文件main.cpp
mainwidget.cpp
subwidget.h
mainwidget.h
subwidget.h
Signal.pro
//main.cpp
#include "mainwidget.h"
#include <QApplication>
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//定义主窗口对象
MainWidget w;
//窗口标题
w.setWindowTitle("这是主窗口");
//窗口显示
w.show();
return a.exec();
}
//mainwidget.c
#include "mainwidget.h"
#include <QDebug>
//主窗口构造函数
MainWidget::MainWidget(QWidget *parent)
: QWidget(parent)
{
//b1按钮设置
b1.setParent(this);
b1.setText("切换副窗口");
b1.move(100,100);
//b1信号处理
connect(&b1,&QPushButton::pressed,this,&MainWidget::myslot1);
//副窗口标题设置
w2.setWindowTitle("这是副窗口");
//副窗口信号处理
connect(&w2,&SubWidget::mysignal,this,&MainWidget::myslot3);
//调整窗口分辨率
resize(400,300);
}
MainWidget::~MainWidget()
{
}
//自定义槽函数1
void MainWidget::myslot1()
{
this->hide();
w2.show();
}
//自定义槽函数3
void MainWidget::myslot3()
{
this->show();
w2.hide();
}
//subwidget.cpp
#include "subwidget.h"
//副窗口构造函数
SubWidget::SubWidget(QWidget *parent) : QWidget(parent)
{
//b2按钮设置
b2.setParent(this);
b2.setText("切换到主窗口");
b2.move(100,100);
//修改分辨率
resize(400,300);
//b2按钮信号处理
connect(&b2,&QPushButton::pressed,this,&SubWidget::myslot2);
}
//槽函数2
void SubWidget::myslot2()
{
//发射信号 用emit修饰
emit mysignal();
}
//mainwidget.h
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
#include <QWidget>
#include <QPushButton>
#include "subwidget.h"
class MainWidget : public QWidget
{
Q_OBJECT
public:
MainWidget(QWidget *parent = 0);
~MainWidget();
//声明槽函数
void myslot1();
void myslot3();
private:
QPushButton b1;
SubWidget w2;
};
#endif // MAINWIDGET_H
//subwidget.h
#ifndef SUBWIDGET_H
#define SUBWIDGET_H
#include <QWidget>
#include <QPushButton>
class SubWidget : public QWidget
{
Q_OBJECT
public:
explicit SubWidget(QWidget *parent = nullptr);
//声明槽函数
void myslot2();
signals:
//定义自定义信号 只声明不定义 需要signals关键字修饰
void mysignal();
public slots:
private:
QPushButton b2;
};
#endif // SUBWIDGET_H
//Signal.pro
//添加模块
QT += core gui
//添加对QT4以上版本的支持 增加兼容性
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
//目标程序名字
TARGET = Signal
TEMPLATE = app
//编译警告输出
DEFINES += QT_DEPRECATED_WARNINGS
//源文件
SOURCES += \
main.cpp \
mainwidget.cpp \
subwidget.cpp
//头文件
HEADERS += \
mainwidget.h \
subwidget.h
内存释放
QT
中从 Q_OBJECT
开始,会为每个对象建立内存依赖树,当对象使用完毕不用,手动释放内存,内存会被自动释放掉
//申请内存空间定义一个按钮
b3 =new QPushButton(this);
b3->setText("小按钮");
b3->move(50,50);
//不定义delete手动释放内存,直接关闭窗口
MainWidget::~MainWidget()
{
qDebug()<<"对象被析构";
}
//能够看到仍然能够进入析构函数
坐标系统
每个对象都会以父对象的左上角为(0,0)
坐标原点