alin的学习之路(QT篇:一)(按钮,信号槽,lambda表达式)

alin的学习之路(QT篇:一)(按钮,信号槽,lambda表达式)

1.QT简介

  1. Qt:1991年由奇趣科技开发

  2. Qt的优点:

    1. 跨平台
    2. 一定程度上简化了内存回收(一些delete可不用添加)
  3. 成功案例:

    1. Linux桌面环境KDE
    2. WPS
    3. 网络电话
    4. 谷歌地图
    5. VLC多媒体播放器
    6. 虚拟机软件

2.QPushButton基本使用

  1. 基本使用

    //创建按钮
    QPushButton *btn = new QPushButton;
    //显示按钮
    //btn->show();
    
    //想要将按钮显示在父界面上,要添加父依赖
    btn->setParent(this);
    
    //设置文本
    btn->setText("你好");
    
    //设置窗口大小
    this->resize(600,400);
    
    //设置大小锁定
    this->setFixedSize(600,400);
    
    //创建第二个按钮  -- 构造函数有5个版本,其中一个(文本,父窗口)
    QPushButton *btn2 = new QPushButton("你好!",this);
    
    //移动按钮2的位置
    btn2->move(100,0);
    
    //设置窗口标题
    this->setWindowTitle("第一个Qt窗口");
    
  2. 自定义按钮

    1. 创建C++源文件,父类选择QWidget
    2. 修改父类为QPushButton
    MyPushButton *mybtn = new MyPushButton;
    mybtn->setParent(this);
    mybtn->setText("自定义按钮");
    mybtn->move(0,100);
    

3.对象树

  1. 当创建的对象父窗口是QObject ,或者是QObject派生下来的类,此对象会放到对象树上,当程序执行完毕,树上的内容会从下往上依次释放
  2. 先执行父类的析构函数,有子类,则执行子类的析构函数;若没有子类,则释放
Widget::~Widget()
{
    qDebug() << "Widget的析构函数调用" ;
}
MyPushButton::~MyPushButton()
{
    qDebug() << "MyPushButton的析构函数调用" ;
}

结果:
Widget的析构函数调用
MyPushButton的析构函数调用

4.信号和槽

  1. connect函数

    1. 参数1:信号的发送者
    2. 参数2:发送的信号
    3. 参数3:信号的接收者
    4. 参数4:处理的槽函数
    //信号槽
    //信号槽在帮助文档中,信号要查看singal,槽函数要查看public slot,如果子类没有写要查看它的父类
    //参数: 1.信号的发送者(指针)  2.发送的信号(地址)  3.信号的接收者(指针)  4.处理的槽函数(地址)
    connect(mybtn,&MyPushButton::clicked,this,&Widget::close);
    
  2. 信号槽优点:松散耦合 :将松散的内容通过信号槽连接起来

  3. 自定义信号和槽

    1. 信号
      1. 写在signals下
      2. 返回值为void
      3. 只需要声明,不需要实现
      4. 可以有参数,可以发生重载
    2. 槽函数
      1. 写在public slots下,高版本可以写在public下、全局函数下或者lambda
      2. 返回值void
      3. 需要声明,需要实现
      4. 可以有参数,可以发生重载
    信号和槽的定义;
    class Teacher : public QObject
    {
        Q_OBJECT
    public:
        explicit Teacher(QObject *parent = nullptr);
    
        //信号函数要写在signals下
        //1.返回值为void
        //2.只需要声明,不需要实现
        //3.可以有参数,可以发生重载
    signals:
        void hungry();
        void hungry(QString foodName);
    public slots:
    };
    
    class Student : public QObject
    {
        Q_OBJECT
    public:
        explicit Student(QObject *parent = nullptr);
    
    signals:
    
        //槽函数要写在public slots下,高版本一些其他的地方也可以
        //1.返回值是void
        //2.需要声明,需要实现
        //3.可以有参数,可以发生重载
    public slots:
        void treat();
        void treat(QString foodName);
    };
    
    
    void Student::treat()
    {
        qDebug() << "请老师吃饭" ;
    }
    
    void Student::treat(QString foodName)
    {
        //使用qDebug()输出QString内容时,会带上一个"",输出char*后无""
        //QString转char*
        //1.toutf8()转为QByteArray
        //2.data()转为char*
        qDebug() << "请老师吃饭,吃" << foodName.toUtf8().data() ;
    }
    
    void Widget::classIsOver()
    {
        emit this->zt->hungry();
        emit this->zt->hungry("宫保鸡丁");
    }
    
    
    信号和槽的使用;
    //创建两个对象,并挂到对象树上,不需要delete
    this->zt = new Teacher(this);
    this->st = new Student(this);
    connect(this->zt,&Teacher::hungry,this->st,&Student::treat);
    classIsOver();    //使用该函数发送老师饿了的信号,emit关键字用于发送信号
    
    //信号和槽发生重载后,需要利用函数指针指向函数地址
    void(Teacher:: *ztSignal)(QString) = &Teacher::hungry;
    void(Student:: *stSlot)(QString) = &Student::treat;
    connect(this->zt,ztSignal,this->st,stSlot);
    
    //添加按钮,按按钮触发信号 老师饿了
    QPushButton *btn = new QPushButton(this);
    btn->setText("下课");
    
    
    //自定义信号:无参
    void(Teacher:: * teacherSignal2)() = &Teacher::hungry;
    void(Student:: * studentSlot2)() = &Student::treat;
    connect(this->zt, teacherSignal2 ,this->st,studentSlot2);
    
    
  4. 信号和槽的扩展

    1. 信号连接信号
    2. 一个信号可以连接多个槽函数
    3. 多个信号可以连接同一个槽函数
    4. 信号和槽的参数类型 必须一一对应
    5. 信号的参数个数可以多于槽函数,反之不可以,相同个数的参数类型也要一一对应
    6. 可以利用 disconnect 断开信号槽的连接
    //信号触发信号 只能触发无参的
    connect(btn,&QPushButton::clicked,this->zt,teacherSignal2);
    
  5. Qt4版本的信号和槽的写法

    1. 优点:参数直观,写法简单
    2. 缺点:编译器不检测参数类型(参数类型不对应时可以运行起来,但是信号和槽触发时报错)
    connect(this->zt,SIGNAL(hungry(QString)),this->st,SLOT(treat(QString)));
    

5.lambda表达式

  1. 基本语法:[](){}; (大括号和分号之间加一对小括号表示调用该匿名函数)

  2. []中的写法:

    1. =:代表值传递
    2. &:代表引用传递
    3. a:代表仅此变量,值传递
    QPushButton *btn2 = new QPushButton("aaa",this);
        btn2->move(100,0);
        [=](){
            btn2->setText("aaa");
        }();
    
  3. 加上mutable修饰符后,可以修改按值传递进来的拷贝

     QPushButton * myBtn = new QPushButton (this);
    QPushButton * myBtn2 = new QPushButton (this);
    myBtn->move(0,100);
    myBtn->setText("myBtn");
    myBtn2->setText("myBtn2");
    myBtn2->move(100,100);
    int m = 10;
    //加上mutable修饰符后,可以修改按值传递进来的拷贝
    connect(myBtn,&QPushButton::clicked,this,[m] () mutable { m = 20; qDebug() << m; });  // 20
    
    connect(myBtn2,&QPushButton::clicked,this,[=] ()  { qDebug() << m; });   // 10
    
    qDebug() << m;   // 10
    
    
  4. 返回值类型: []()->return type{};

    int num = []()->int{return 1000;}();
    qDebug() << num ;
    
  5. connect与lambda一起使用

    //connect与lambda表达式一起用
    QPushButton * btn3 = new QPushButton;
    btn3->setParent(this);
    btn3->move(200,200);
    btn3->setText("aaa");
    connect(btn3,&QPushButton::clicked,[=](){
        btn3->setText("bbb");
        this->st->treat("鱼香肉丝");
        this->close();
    });
    

你可能感兴趣的:(C++,Qt)