目录
3.方法三:继承QPushButton类,自定义 MyQPushBtn类。
一、创建QPushButton
1.方法一:
QPushButton *btn=new QPushButton;
// btn->show();//以顶层的方式单独弹出窗口控件
btn->setParent(this);
btn->setText("第一个按钮");
btn->move(0,100);
2.方法二:按照按钮的大小创建窗口。
QPushButton *btn2=new QPushButton("第二个按钮",this);
搭配使用->重置窗口大小:
//重置窗口大小
this->resize (600,400);
//移动位置
btn2->move(100,100);
扩展:
//设置固定窗口大小,不可拖拽
this->setFixedSize(600,400);
//设置窗口标题
setWindowTitle("QPushBtn Study");
3.方法三:继承QPushButton类,自定义 MyQPushBtn类。
//myqpushbtn.h
#ifndef MYQPUSHBTN_H
#define MYQPUSHBTN_H
#include <QPushButton>
#include <QDebug>
class MyQPushBtn : public QPushButton
{
Q_OBJECT //Q_OBJECT宏,允许类中使用信号和槽机制
public:
explicit MyQPushBtn(QWidget *parent = nullptr);
~MyQPushBtn();
signals:
};
#endif // MYQPUSHBTN_H
//myqpushbtn.cpp
#include "myqpushbtn.h"
MyQPushBtn::MyQPushBtn(QWidget *parent) : QPushButton(parent)
{
}
MyQPushBtn::~MyQPushBtn()
{
qDebug()<<"~MyQPushBtn";
}
MyQPushBtn的使用:
#include "widget.h"
Widget::Widget(QWidget *parent): QWidget(parent)
{
MyQPushBtn *btn3=new MyQPushBtn(this);
btn3->setText("第三个按钮");
btn3->move(200,100);
}
Widget::~Widget()
{
qDebug()<<"~Widget";
}
扩展:对象树
更多细节:https://zhuanlan.zhihu.com/p/43523879
QObject是QT中所有类的基类(所以QObject是QWidget的基类),QWidget是所有UI Widget类的基类。
//QObject
typedef QList<QObject*> QObjectList;
inline const QObjectList &children() const { return d_ptr->children; }
Qt 引入对象树的概念,在一定程度上解决了内存问题。QObject 类就有一个私有变量 QList<QObject *>,专门存储这个类的子孙后代们。当创建一个QObject对象时,会看到QObject的构造函数接收一个QObject指针作为参数,这个参数就是 parent,也就是父对象指针,这时QObject对象就会把自己加入到父对象的 children() 列表中,也就是 QList<QObject *> 变量中。对象树的好处就是:当父对象析构的时候,这个列表中的所有对象也会被析构。(注意,这里的父对象并不是继承意义上的父类!)
*比如上方代码,创建btn3时,会把btn3加入到Widget的children列表中。当Widget析构时,btn3也会被析构。所以根据“后创建的先析构”规则,我们关闭Widget时,会先析构btn3,再析构Widget。
二、自定义信号和槽
connect(信号的发送者,发送的具体信号(函数的地址),信号的接收者,信号的处理(函数的地址));
实现点击按钮,关闭窗口:
connect(btn,&QPushButton::clicked,this,&QWidget::close);
connect(btn2,&QPushButton::clicked,this,&Widget::close);
connect(btn3,&MyQPushBtn::clicked,this,&Widget::close);
1.无参信号和槽
(实现:当老师说饿时,学生说请客)
a.信号
- 写到signals下。
- 返回值void,只需要申明,不需要实现。
- 可以有参数,可以重载。
b.槽
- 早期qt版本,槽函数需要写在public slots下,现在的qt版本,全局函数可以作为槽函数。
- 返回值void,需要申明,需要实现。
- 可以有参数,可以重载。
c.信号和槽的关系
- 信号的参数个数可以大于等于槽的参数个数,但信号和槽的参数类型需要一一对应。
- 一个信号可以连接多个槽函数。
- 一个信号可以连接到另外的一个信号。
- 多个信号可以连接到一个槽。
- 信号和槽可以断开连接。
* 创建Teacher类和Student类:无参
//teacher.h
#ifndef TEACHER_H
#define TEACHER_H
#include <QObject>
class Teacher : public QObject
{
Q_OBJECT
public:
explicit Teacher(QObject *parent = nullptr);
signals:
void Hungry();
};
#endif // TEACHER_H
//********************************************************
//teacher.cpp
#include "teacher.h"
Teacher::Teacher(QObject *parent) : QObject(parent)
{
}
//student.h
#ifndef STUDENT_H
#define STUDENT_H
#include <QObject>
#include <QDebug>
class Student : public QObject
{
Q_OBJECT
public:
explicit Student(QObject *parent = nullptr);
signals:
public slots:// 可有可无
void Treat();
};
#endif // STUDENT_H
//********************************************************
//student.cpp
#include "student.h"
Student::Student(QObject *parent) : QObject(parent)
{
}
void Student::Treat()
{
qDebug()<<"我请客";
}
2.关联无参信号和槽
//widget.h中声明变量和方法:
Teacher *teacher;
Student *stu;
void TeacherSpeech();
//widget.cpp中实现方法并关联信号和槽
void Widget::TeacherSpeech()
{
emit teacher->Hungry();//emit 触发自定义信号
}
Widget::Widget(QWidget *parent): QWidget(parent)
{
teacher=new Teacher(this);
stu =new Student(this);
connect(teacher,&Teacher::Hungry,stu,&Student::Treat);//连接信号和槽
//触发信号
TeacherSpeech();//方法一:直接触发信号
connect(btn3,&MyQPushBtn::clicked,this,&Widget::TeacherSpeech);//方法二:通过信号槽触发信号
}
3.信号和槽的重载
修改信号和槽,实现信号和槽的重载:
//teacher.h 补充Hungry的重载
#ifndef TEACHER_H
#define TEACHER_H
#include <QObject>
class Teacher : public QObject
{
Q_OBJECT
public:
explicit Teacher(QObject *parent = nullptr);
signals:
void Hungry();
void Hungry(QString foodName);
};
#endif // TEACHER_H
//********************************************************
//teacher.cpp
#include "teacher.h"
Teacher::Teacher(QObject *parent) : QObject(parent)
{
}
//student.h ,补充Treat的重载
#ifndef STUDENT_H
#define STUDENT_H
#include <QObject>
#include <QDebug>
class Student : public QObject
{
Q_OBJECT
public:
explicit Student(QObject *parent = nullptr);
signals:
public slots:// 可有可无
void Treat();
void Treat(QString foodName);
};
#endif // STUDENT_H
//********************************************************
//student.cpp
#include "student.h"
Student::Student(QObject *parent) : QObject(parent)
{
}
void Student::Treat()
{
qDebug()<<"我请客";
}
void Student::Treat(QString foodName)
{
qDebug()<<"我请客,吃"<<foodName.toUtf8().data();//我请客,吃 火锅
// qDebug()<<"我请客,吃"<<foodName;//我请客,吃 "火锅"
}
4.关联有重载的信号和槽
当信号和槽有重载时,使用connect(teacher,&Teacher::Hungry,stu,&Student::Treat);来关联信号和槽便会报错,因为它不清楚我们关联的是哪个信号和哪个槽,此时,我们需要使用以下方法来关联:
//带参的信号和带参的槽:
void Widget::TeacherSpeech()
{
emit teacher->Hungry("火锅");
}
Widget::Widget(QWidget *parent): QWidget(parent)
{
teacher=new Teacher(this);
stu =new Student(this);
void (Teacher:: *teacherSignals)(QString)=&Teacher::Hungry;
void (Student:: *studentSlots)(QString)=&Student::Treat;
connect(teacher,teacherSignals,stu,studentSlots);
TeacherSpeech();//直接触发信号
//不能通过点击按钮来触发teacherSignals,因为clicked的参数类型和teacherSignals的参数类型不一样
//connect(btn3,&MyQPushBtn::clicked,teacher,teacherSignals);//错误
}
//不带参的信号和不带参的槽:
void Widget::TeacherSpeech()
{
emit teacher->Hungry();
}
Widget::Widget(QWidget *parent): QWidget(parent)
{
teacher=new Teacher(this);
stu =new Student(this);
void (Teacher:: *teacherSignals1)(void)=&Teacher::Hungry;
void (Student:: *studentSlots1)(void)=&Student::Treat;
connect(teacher,teacherSignals1,stu,studentSlots1);
TeacherSpeech();//直接触发信号
connect(btn2,&MyQPushBtn::clicked,teacher,teacherSignals1);//信号信号-触发信号,一个信号可以连接到另外的一个信号
}
//带参的信号和不带参的槽:信号的参数个数可以大于等于槽的参数个数
void Widget::TeacherSpeech()
{
emit teacher->Hungry("火锅");
}
Widget::Widget(QWidget *parent): QWidget(parent)
{
teacher=new Teacher(this);
stu =new Student(this);
void (Teacher:: *teacherSignals)(QString)=&Teacher::Hungry;
void (Student:: *studentSlots)(void)=&Student::Treat;
connect(teacher,teacherSignals,stu,studentSlots);
TeacherSpeech();//直接触发信号
}
5.信号和槽、信号和信号的断开
disconnect(btn2,&MyQPushBtn::clicked,teacher,teacherSignals1);