什么是Qt
Qt是一个跨平台的C++图形用户界面应用程序框架,,它为应用程序开发者提供建立以数据图形界面所需的所有功能,它是完全面向对象的,很容易扩展,并且允许真正的组件编程
Qt卡死解决方案:
与某些软件不兼容导致的原因:在本机上为与《网易有道词典》相冲突,退出词典即可
中文乱码问题解决:
#pragma execution_character_set("utf-8")
Qt项目框架及文件介绍
文件名:main.cpp
#include "widget.h"
#include <QApplication> //Qt系统提供的标准类名声明头文件
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
QPushButton *button = new QPushButton; //新建按钮
this->setWindowTitle("这是标题"); //设置标题
this->resize(100000,10); //设置可拉伸窗口
this->setFixedSize(1960,1080); //设置不可拉伸窗口
button -> show(); //在另一个窗口显示
button -> setParent(this); //设置按钮的父对象为窗口,这样按钮就在窗口上显示了
button -> move(x,y); //设置按钮位置
Qt对象树:不全且杂乱无章:
自定义按钮类继承QPushButton,实例化自定义按钮类,并将其添加窗口类,实现构造与析构,然后关闭窗口,看析构函数是否自动执行,使用注意:在Qt中,尽量在构造的时候就指定parent对象,并且大胆地在堆上构造
该段代码无问题:因为栈一般先构造的,反而后面才析构
下面程序是先析构button,同时将button从window的子对象列表删除
然后析构window,仅析构window,因为window无子对象
QWidge window;
QPushButton button = QPushButton(“退出”,&window)
该段代码有问题:因为栈一般先构造的后析构(同上)
下面程序是先析构window,因为先构造的后析构,所以说要析构window及其子对象(quit),
然后析构quit,导致quit重复析构,程序崩溃
QPushButton quit("Quit");
QWidget window;
quit.setParent(&window);
信号和槽机制
信号槽是Qt框架引以为豪的机制。所谓信号槽,实际就是观察者模式。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,他就会使用连接(connect)函数。意思是,将想要处理的信号和自己的一个函数(称为槽(slot))绑定来处理这个信号。也就是说,当信号发出时,被连接的槽函数会自动被回调。这就类似观察者模式;当发生了感兴趣的事件,某一个操作就会自动被触发。
优点:松散耦合,信号的发送端和接收端可以毫无关联,如果要关联就用connect函数
在添加C++类的时候第一个字母一定大写
connect函数 && 系统自带的信号和槽
connect(sender, signal, receiver, slot)
sender:信号发出者
signal:信号
receiver:信号接收者(感兴趣者)
slot:接收后执行的任务(槽函数)
信号:举例:QPushButton类信号:索引查找QPushButton,发现无信号,找它基类
Inherits: QAbstractButton 然后找Signals
槽函数:公共槽函数见帮助 -> 索引 -> 左上查找QWidget -> 双击打开 -> Public Slots
举例:点击窗口按钮,关闭窗口
拓展:点击自定义按钮,关闭窗口
MyButton *button = new MyButton();
button -> setParent(this);
button -> setText("关闭");
connect(button, &QPushButton::clicked, this, &Widget::close);
自定义信号和槽:老师饿了,学生请客
步骤1:确定场景:老师饿了,学生请客
步骤2:添加老师类和学生类
步骤3:在老师类中声明信号,在学生中声明并实现槽函数
在刚创建的teacher.h中
public内:signals: void hungry();
信号返回值void,参数可以存在,仅声明,不需要实现,可以重载
注意:在此步骤中,信号不需要实现,有即可
在刚创建的student.h中
public内: public slots: void treat(); ——声明treat函数
定义treat():在刚创建的student.cpp内:创建一个函数
void Student::treat()
{
qDebug("请老师吃饭");
}
步骤4:创建对象+信号与槽连接
把头文件引入到widget.h中
在widget.h内:public内: Teacher *tea; Student *stu;
.cpp内:
this -> stu = new Student();
this -> tea = new Teacher();
connect(tea, &Teacher::hungry, stu, &Student::treat);
步骤5:触发信号
使用emit,具体为 emit tea -> hungry();
另:点击按钮,触发取快递,如下
connect(button2, &QPushButton::clicked, this, &Widget::Express);
connect(shitbro, &EMS::PengPengPeng, Me, &Familys::Receive);
void Widget::Express()
{
emit shitbro -> PengPengPeng();
}
法二:信号连接信号
connect(button2, &QPushButton::clicked, shitbro, &EMS::PengPengPneg);
connect(shitbro, &EMS::PengPengPeng, Me, &Familys::Receive);
就是个信号的传递
自定义槽函数注意事项:
1、发送者与接受者需要是QObject的子类(槽函数为全局,Lambda表达式除外)
2、信号和槽函数返回值都是void
3、信号需要声明,不需要定义实现,槽函数需要声明也需要定义实现
4、槽函数是普通的成员函数,作为成员函数,会受到public、private、protected的影响
7、任何成员函数、static函数、全局函数和Lambda表达式都可以作为槽函数
8、信号槽要求信号和槽的参数一致,所谓一致,是指参数类型一致
如果信号和槽的参数不一致,允许的情况是:槽函数的参数可以比信号的稍,即便如此,槽
函数存在的那些参数的顺序也必须和信号的前面几个一致。这是因为,你可以在槽函数中选择忽略
信号传来的数据(也就是槽函数的参数比信号的少)
举例:
signal(QSting)和slot(Qsting)√
singal(QSting,int)和slot(QSting)√
signal(QSting)和slot(QSting,int)× 理由:没那参数slot从哪往出取?
signal(QSting,QSting,int)和slot(QSting,QSting)√
signal(QSting,QSting,int)和slot(QSting,int) × 不能跳过取参数
信号槽的拓展:
一个信号可以和多个槽相连:如果是这种情况,这些槽会一个接一个地被调用,但是他们的调用顺序是不确定的
多个信号可以连接到一个槽:只要任意一个信号发出,这个槽就会被调用
一个信号可以连接到另外的一个信号:当第一个信号发出时,第二个信号被发出。除此之外,这种信号—信号的形式和信号—槽的形式没什么区别
槽可以被断开链接(disconnect),槽也可以被取消链接(当一个对象delete了,那么取消这个对象上的槽)
使用C++11中的Lambda表达式