Qt 学习第二天
2.1 QPushButton 的运用(按钮)
相关文档:
使用前需先引用头文件 #include <QPushButton>。
同时为防止汉字乱码,需使用QString::fromLocal8Bit()包裹汉字。
// 第一种运用方法(调用方法传参)
QPushButton* btn = new QPushButton;
btn->setParent(this);
btn->setText(QString::fromLocal8Bit("按钮"));
// 第二种运用方法(构造时传参)
QPushButton* btn2 = new QPushButton(QString::fromLocal8Bit("按钮2"), this);
// 设置按钮位置
btn2->move(100, 100);
// 设置按钮大小
btn2->resize(100, 100);
运行结果:
2.2 对象模型(对象树)
QObject 是以对象树的形式组织起来的。
- 当你创建一个 QObject 对象时,会看到 QObject 的构造函数接收一个 QObject 指针作为参数,这个参数就是 parent,也就是父对象指针。
- 这相当于,在创建 QObject 对象时,可以提供一个其父对象,我们创建的这个 QObject 对象自动添加到其父对象的 children() 列表。
- 当父对象析构的时候,这个列表中的所有对象也会被析构。(注意,这里的父对象并不是继承意义上的父类!)
- 这种机制在 GUI 程序设计中相当有用。例如,一个按钮有一个Shortcut(快捷键)对象作为其子对象。当我们删除按钮的时候,这个快键理应被删除。这是合理的。
Qwidget是能够在屏幕上显示的一切组件的父类。
- Qwidget继承自 QObject,因此也继承了这种对象树关系。一个孩子自动地成为父组件的一个子组件。因此,它会显示在父组件的坐标系统中,被父件的边界剪裁。例如,当用户关闭一个对话框的时侯,应用程序将其删除,那么,我们希望属于这个对话框的按钮、图标等应该一起被删除。事实就是如此,因为这些都是对话框的子组件。
2.3 Qt 的坐标系
2.4 信号和槽
2.4.1 初识信号和槽
connect(信号的发送者,发送的具体信号,信号的接受者,信号的处理(槽))
信号槽的优点,松散耦合,信号发送端和接受端本身是没有关联的,通过connect连接将两端耦合在一起。
例:QPushButton 的父类 QAbstractButton 文档中可查询到信号
例:QWidget 文档中可查询到槽函数
// 使用信号和槽 点击按钮2 关闭窗口
// 参数1 信号的发送者 参数2发送的信号(函数的地址)参数3 信号的接受者 参数4处理的槽函数
connect(btn2, &QPushButton::clicked, this, &QWidget::close);
2.4.2 自定义信号和槽
需求:
创建 Teacher 类老师类 、 Student 类学生类
下课后,老师会触发一个信号,饿了,学生响应信号,请客吃饭。
首先右键项目创建 Teacher 和 Student 两个基类是 QObject 的 c++ class。
在 Teacher 类头文件中 signals 部分添加无参和有参函数,即为自定义信号量。
注:
自定义信号写到 signals下
返回值是void,只需要声明,不需要实现
可以有参数,可以重载
在 Student 类头文件中 public 部分添加无参和有参函数,即为自定义槽函数。
注:
早期 Qt 版本必须要写到 public slots,高级版本可以写到 public 或者全局下
返回值 void,需要声明,也需要实现
可以有参数,可以发生重载
实现:
随后在基类是 QWidget 的类头文件中添加成员变量和下课函数。
基类是 QWidget 的类实现部分总体如下:
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
this->zt = new Teacher(this);
this->st = new Student(this);
//连接有参槽
void(Teacher::*teachersignal)(QString) =&Teacher::hungry;
void(Student::*studentslot)(QString) =&Student::treat;
connect(zt,teachersignal,st,studentslot);
QPushButton *btn = new QPushButton("下课",this);
this->resize(600, 400);
//触发自定义槽函数
//connect(btn, &QPushButton::clicked, this, &Widget::classIsOver);
//连接无参槽
void(Teacher::*teachersignal2)(void) =&Teacher::hungry;
void(Student::*studentslot2)(void) =&Student::treat;
connect(zt,teachersignal2,st,studentslot2);
//信号连接信号
connect(btn, &QPushButton::clicked, zt, teachersignal2);
//断开信号
//disconnect(zt,teachersignal2,st,studentslot2);
//一个信号连接多个槽函数
connect(zt,teachersignal2,this, &Widget::classIsOver);
//引入lambda
int m = []()->int{return 10;}();
QPushButton *btn2 = new QPushButton("按钮2",this);
btn2->move(100, 100);
connect(btn2, &QPushButton::clicked, this, [=](){qDebug()<<m;});
//lambda应用
QPushButton *btn3 = new QPushButton("点我关闭",this);
btn3->move(100, 0);
connect(btn3, &QPushButton::clicked, this, [=](){
this->close();
});
}
Widget::~Widget()
{
delete ui;
}
void Widget::classIsOver()
{
// 无参版本
// emit zt->hungry();
// 有参版本
emit zt->hungry("宫保鸡丁");
}
点击下课按钮,会调用有参和无参槽函数。其中无参槽函数的唤醒是通过信号连接信号实现的。
点击按钮2,会通过lambda表达式输出m的值
最后点击点我关闭,则会关闭窗口
注意事项:
- 信号/槽函数参数数个数是可以不一样的,槽函数参数个数可以少于信号的参数个数,反之不可。
- 信号/槽函数参数必须一一对应。