C++ | 通过QPushButton学习Qt基本语法 [ 对象树、自定义信号和槽 ]

19 篇文章 5 订阅

目录

一、创建QPushButton

1.方法一:

2.方法二:按照按钮的大小创建窗口。

3.方法三:继承QPushButton类,自定义 MyQPushBtn类。

扩展:对象树 

二、自定义信号和槽

1.无参信号和槽

a.信号

b.槽

c.信号和槽的关系

2.关联无参信号和槽 

3.信号和槽的重载

4.关联有重载的信号和槽

5.信号和槽、信号和信号的断开


一、创建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.信号

  1. 写到signals下。
  2. 返回值void,只需要申明,不需要实现。
  3. 可以有参数,可以重载。

b.槽

  1. 早期qt版本,槽函数需要写在public slots下,现在的qt版本,全局函数可以作为槽函数。
  2. 返回值void,需要申明,需要实现。
  3. 可以有参数,可以重载。

c.信号和槽的关系

  1. 信号的参数个数可以大于等于槽的参数个数,但信号和槽的参数类型需要一一对应。
  2. 一个信号可以连接多个槽函数。
  3. 一个信号可以连接到另外的一个信号。
  4. 多个信号可以连接到一个槽。
  5. 信号和槽可以断开连接。

* 创建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);

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

烫青菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值