day02C++QT框架学习

 

按钮的定义 
   //connnect (信号的发送者,发送信号、信号的接受者、处理的函数(槽函数))

 

    //点击myBtn 关闭窗口

 

    //参数1 信号发送者 参数2 发送的信号 参数3 信号的接收者 参数4 处理的槽函数(函数地址)

 

    //高版本中去掉取地址符也可以运行,但是为了兼容性还是建议书写
  //myBtn和btn是QPushButton的对象
  //实现代码为:
  MyButton * myBtn = new MyButton;
  QPushButton * btn = new QPushButton;
  //单单这么写是不会显示我们自定义的按钮的,因为没有调用他进行显示
  可以调用show()方法或者在创建对象时这样书写:
  QPushButton * myBtn = new QPushButton("按钮上的文字", this)

  //使用connect函数可以让我们点击按钮时触发对应函

 

    connect(myBtn, &MyButton::clicked, this, &Widget::close);

 

    connect(btn,&QPushButton::clicked, this, &Widget::close);

 

    //由于MyButton的作用域是在QPushButton中的,所以我们完全可以将发送信号的作用域用QPushButton的地址

 

    //优点:松散耦合 将两个集合连接起来

下面使用connect实现需求

 //有一个需求 刚刚创建的按钮没有作用 现在我想点击我的按钮 关闭窗口

    //按钮->点击 窗口->关闭
    //我们需要将这些功能连接起来
  信号发出者->发送信号->信号的接收者->接收者调用自己的函数(槽函数)
  创建两个类一个类是Student类 一个是学生类 老师类发出信号"hungry" 学生接收信号"treat"请客
  student.h的定义:
#define STUDENT_H
#include <QObject>
class Student : public QObject
{
    Q_OBJECT//添加这句可以使用信号和槽函数
public:
    explicit Student(QObject *parent = nullptr);
signals://信号编写位置
public slots://槽函数编写位置
    //自定义槽函数
    //高版本可以写道 public下或者全局函数
    //槽函数返回值为空
    //槽函数需要声明也需要实现
    //槽函数也可以有参数 可以发生重载
    void treat();//有参的定义
    void treat(QString foodName);//无参的定义
};
#endif // STUDENT_H

   #ifndef TEACHER_H
#define TEACHER_H


Teacher.h文件的定义:
#include <QObject>
class Teacher : public QObject
{
    Q_OBJECT
public:
    explicit Teacher(QObject *parent = nullptr);
    //自定义信号需要卸载signals中
signals://信号编写位置
    //返回类型必须是void
    //信号只需要声明 不需要实现
    //信号可以传递参数,可以重载
    void hungry();//有参的定义
    void hungry(QString foodName);//无参的定义
};
#endif // TEACHER_H

主窗口定义Widget.h定义:

#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include<QPushButton>
#include<QDebug>
#include"teacher.h"
#include"student.h"
class Widget : public QWidget
{
  
   Q_OBJECT
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
    Teacher * zt;

    Student * st;
    void classIsOver();
};
#endif // WIDGET_H

student.cpp定义
#include "student.h"
#include<QDebug>
Student::Student(QObject *parent) : QObject(parent)
{
}
void Student::treat()
{
    qDebug() << "请老师吃饭";
}
void Student::treat(QString foodName)
{
     // qDebug() << "请老师吃饭,老师要吃"<< foodName;

    //去掉输出的时候带引号的问题 foodName带引号的问题

    //QString 转char* toUtf8转QByteArray 在利用data 转成char*

    qDebug() << "请老师吃饭,老师要吃" << foodName.toUtf8().data();
}
void Student::study(QString Objcet)
{
    qDebug() << "学生要上课,上的科目是" << Objcet.toUtf8().data();
}


由于Teacher类只是信号的发出者 信号只用声明不用实现这里Teacher.cpp中是QT框架原本定义

   综上,Teacher类发出信号hungry -> 学生类接收信号后处理 -> 调用treat()
下面进行函数的实现:

/*添加类的时候忘记添加Q_OBJECT导致无法使用其槽函数等信号,我们需要在头文件中每个类的花括号下写入Q_OBJECT 然后修改.pro文件就可以了*/
//例如
/*#include <QObject>
class Student : public QObject
{
    Q_OBJECT
public:
    explicit Student(QObject *parent = nullptr);
*/
//此时修改.pro文件添加空格或者删除空行使得qmake能够运行 就可以正常运行
#include "widget.h"
#include <QWidget>
#include<QPushButton>
#include<QDebug>
#include"teacher.h"
#include"student.h"

//需求:创建两个类 Teacher  Stdent 
//下课后 老师Teacher zt 会发出一个信号 饿了
//zt 信号发送者 学生类响应信号
//处理信号的槽函数 请客吃饭
//学习自定信号
//老师类是信号的发出方 所以会在老师类中编写信号
//由于学生类是信号的接收方 所以会在学生类中书写槽函数
//信号是不用实现的只用声明 可以给予参数 槽函数必须声明必须实现



Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    zt = new Teacher(this);//等于将老师类放到childen表中,之后就不用担心程序的释放
    st = new Student(this);
    //连接老师和学生
   //connect(zt, &Teacher::hungry, st, &Student::treat);
    //不触发按钮 就不会发生


    //有参数的槽的连接
    //函数指针 执行函数地址
    //void(Teacher:: *teacherSignal)(QString) = &Teacher::hungry;
    //void(Student:: *stSlot)(QString) = &Student::treat;
    //connect(zt, teacherSignal, st, stSlot);
    //teacherSignal和StudentSlot本就是指针变量,指针里面存的是地址,所以这里不用取地址符


     //函数调用
     //classIsOver();

     //点击下课 才下课
     QPushButton * over_btn = new QPushButton("点击按钮下课",this);

     //创建函数指针 由于这里我们定义了一个有参的情况一个无参的情况 程序指向不明 我们定义函数指针指向无参的函数使得 指向明确
     void(Teacher:: *noTeacherSignal)(void) = &Teacher::hungry;
     void(Student:: *noStSlot)(void) = &Student::treat;

     //触发按钮
     connect(over_btn, &QPushButton::clicked, zt, noTeacherSignal);//下课按钮
     connect(zt,noTeacherSignal,st,noStSlot);
     //connect(over_btn,&QPushButton::clicked,this,&Widget::close);//一个按钮可以触发多个槽函数
    //重新设置窗口大小
     resize(600,400);

     //断开信号槽disconnect()
     //disconnect(zt,noTeacherSignal,st,noStSlot);

     //信号和槽的拓展
     //1.信号可以连接信号
     //2.信号和槽可以断开disconnect
     //3.一个信号可以触发多个槽函数
     //4.多个信号可以连接一个槽函数
     //5.信号和槽的参数必须一一对应 信号的参数个数 可以多于槽函数的参数个数,但是必须类型一一对应
     //槽函数的参数个数不能多于信号个数
     //相当于需求可以有很多,但提供可以比需求少,反之,提供比需求多,会浪费资源


     //QT4版本 信号和槽写法
     connect(zt,SIGNAL(hungry(QString)), st, SLOT(treat(QString)));
     classIsOver();
     //不推荐QT4版本 当两个对应的类型不同时例如:
     //优点:参数类型比较直观,发生重载也不用写函数指针
     //缺点:参数类型不匹配时,编译器不会报错,但运行的时候就会报错
     connect(zt,SIGNAL(hungry(QString)), st, SLOT(treat(void)));
     connect(zt,SIGNAL(hungry(void)), st, SLOT(treat(QString)));
     //不检测原因
     //SIGNAL和SLOT下会把里面代码作为字符串处理


     //Lambda表达式C++11支持Lambda 如果QT的版本过低的话需要在.pro文件中添加CONFUG += C++11

     QPushButton * btn2 = new QPushButton("aaaa",this);

     //[=](){}这是一个函数 添加()调用函数 这里的“=”是用来将作用范围内所有可见的局部变量 只有当有"="号的时候该函数才能找到变量
     [=](){
         btn2->setText("bbbb");
         //btn-setText("cccc");这里由于[]中只有btn2这个时候btn无法在这个函数中被调用
     }();

     //mutable关键字 用于修改值传递的变量 进行修改
     QPushButton * MyBtn = new QPushButton(this);
     QPushButton * MyBtn2 = new QPushButton(this);
     MyBtn2->move(100, 100);
     int m = 10;
     connect(MyBtn, &QPushButton::clicked, this, [m]()mutable{m = 100 + 10; qDebug() << m;});
     connect(MyBtn2,&QPushButton::clicked, this, [=]{ qDebug() << m;});
     qDebug() << m;


     //返回值
     int ret = []()->int{return 10000;}();
     qDebug() << "ret = " << ret;

    //用的最频繁的[=](){}
     QPushButton * btn3 = new QPushButton("btn3", this);
     btn3->move(200,0);
     connect(btn3, &QPushButton::clicked,this, [=]()
     {
        btn3->setText("DDDDDDD");
     });

     //当我们的[]中使用&取地址符时
//     connect(btn3, &QPushButton::clicked,this, [&]()
//     {
//        btn3->setText("DDDDDDD");
//     });
     //程序会崩掉


     //做信号槽连接,默认内部变量会进行锁的状态,类似与只读状态,如果进行操作,程序会奔溃所以建议使用“="

     //无参按钮调用 有参 请客吃饭
     connect(btn3,&QPushButton::clicked, this, [=]()
     {
        zt->hungry("宫爆鸡丁");
     });

     //点击按钮程序关闭
     connect(btn3, &QPushButton::clicked,this, [=]()
     {
        this->close();
     }
     );

}

void Widget::classIsOver()
{
    //触发老师饿了的信号
    //老师饿了的信号属于自定义信号,触发自定义信号关键字 emit
   // emit zt->hungry();//触发无参信号
   emit zt->hungry("宫保鸡丁");//触发有参的信号
}



 
posted @   华岁渡春风  阅读(73)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
点击右上角即可分享
微信分享提示