QTday2(信号与槽机制——很重要!!!)

一、Xmind整理:

二、上课笔记整理:

1.信号与槽

class Widget : public QWidget
{
    Q_OBJECT        //信号与槽的元对象

signals:
    void my_signal();          //自定义信号函数

public slots:
    void my_slot();            //自定义的槽函数

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
};

2.qt4版本的连接函数,该版本的连接是不友好的连接

[static] QMetaObject::Connection           //返回值是一个连接,并且该函数是一个静态成员函数
    QObject::connect(                      //函数名
        const QObject *sender,             //信号的发射者,是组件的指针
        const char *signal,                //要发射的信号是一个C语言风格的字符串,将信号函数传递进来时,需要使用SIGNAL宏进行转换
        const QObject *receiver,           //信号的接受者,是组件的指针
        const char *method)                //处理信号的槽函数,是C风格字符串,将槽函数传递进来时,需要使用SLOT宏进行转换
注意:信号函数必须是信号的发射者所在的类中有的信号函数,而槽函数也必须是信号的接受者中有的槽函数
举个例子:
  QLabel *label = new QLabel;
  QScrollBar *scrollBar = new QScrollBar;
  QObject::connect(scrollBar, SIGNAL(valueChanged(int)),
                   label,  SLOT(setNum(int)));

3.qt5版本的连接函数

[static] QMetaObject::Connection           //返回值是一个连接,并且该函数是一个静态成员函数
    QObject::connect(                   //函数名
        const QObject *sender,              //信号的发射者,是组件的指针
        PointerToMemberFunction signal,     //信号函数的函数指针变量,直接填写函数名即可
        const QObject *receiver,           //信号的接受者,是组件的指针
        PointerToMemberFunction method)    //槽函数的函数指针变量,直接填写函数名即可
        
举个例子:
  QLabel *label = new QLabel;
  QLineEdit *lineEdit = new QLineEdit;
  QObject::connect(lineEdit, &QLineEdit::textChanged,
                   label,  &QLabel::setText);

4.信号连接外部函数或lambda表达式

[static] QMetaObject::Connection                //返回值是一个连接,并且该函数是一个静态成员函数
    QObject::connect(                 //函数名
        const QObject *sender,            //信号的发射者,是组件的指针
        PointerToMemberFunction signal,      //信号函数的函数指针变量,直接填写函数名即可
        Functor functor)                 //处理信号的功能函数,可以是全局函数,也可以是lambda表达式

举个例子:
  void someFunction();
  QPushButton *button = new QPushButton;
  QObject::connect(button, &QPushButton::clicked, someFunction);

Lambda 表达式作为槽函数:

  QByteArray page = ...;
  QTcpSocket *socket = new QTcpSocket;
  socket->connectToHost("qt-project.org", 80);
  QObject::connect(socket, &QTcpSocket::connected, [=] () {
          socket->write("GET " + page + "\r\n");
      });

5.断开信号与槽的连接

//断开按钮对应的槽函数
void Widget::on_btn6_clicked()
{
    disconnect(btn3, SIGNAL(pressed()), ui->btn1, SLOT(hide()));

    disconnect(ui->btn4, &QPushButton::clicked, this, &Widget::my_slot);

}

6.信号与槽的案例

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<QDebug>
#include<QPushButton>
#include<QTextToSpeech>          //文本转语音的头文件

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT        //信号与槽的元对象

signals:
    void my_signal();          //自定义信号函数

public slots:
    void my_slot();            //自定义的槽函数

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_btn2_clicked();

    void on_btn6_clicked();

private:
    Ui::Widget *ui;

    //自定义一个按钮
    QPushButton *btn3;

    //定义一个播报员指针
    QTextToSpeech *speecher;

};
#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"

void fun()
{
    qDebug()<<"我是过路的";
}

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //给播报员实例化空间
    speecher = new QTextToSpeech(this);

    //给btn3实例化空间
    this->btn3 = new QPushButton("按钮3", this);
    this->btn3->move(ui->btn2->x(), ui->btn2->y()+50);
    this->btn3->resize(ui->btn2->size());

    //使用qt4版本的连接,将按钮3发射的pressed信号与按钮1的槽函数进行连接
    connect(btn3, SIGNAL(pressed()), ui->btn1, SLOT(hide()));
    //参数1:信号的发射者,按钮3的指针
    //参数2:要发射的信号,是在按钮所在类中拥有的信号函数,需要使用SIGNAL宏函数进行转换
    //参数3:信号的接受者,ui界面上的按钮1指针
    //参数4:处理信号的槽函数,是信号接收者所在类中拥有的槽函数
    //注意:该链接方式是不友好的链接,原因是 即使宏函数中写错,编译器不报错,但是没有现象

    //使用qt5版本的链接,将ui界面上的btn4按钮发射的clicked信号,与当前界面的自定义的槽函数连接
    connect(ui->btn4, &QPushButton::clicked, this, &Widget::my_slot);

    //将ui界面上的按钮5,发射的clicked信号,连接到全局函数中
    connect(ui->btn5, &QPushButton::clicked, fun);

    //将ui界面上的按钮5发射的clicked信号连接到lambda表达式中
    connect(ui->btn5, &QPushButton::clicked, [&](){
    //        qDebug()<<"我是路人乙";
        speecher->say("我是路人乙");
    });
    //将当前界面的my_signal信号连接到自定义的槽函数中
    connect(this, &Widget::my_signal, [&](){
        speecher->say("已经成功断开按钮3和按钮4的连接");
    });
}

Widget::~Widget()
{
    delete ui;
}

//自定义槽函数的实现
void Widget::my_slot()
{
    static  int num = 0;
    if(num%2)
    {
        ui->btn2->setEnabled(false);
    }else
    {
        ui->btn2->setEnabled(true);
    }
    num++;
}

//该函数就是按钮2的clicked信号对应的槽函数
void Widget::on_btn2_clicked()
{
    static int num = 0;


    if(num % 3 == 0)
    {
        ui->btn2->setStyleSheet("background-color:red;");
    }else if(num % 3 == 1)
    {
        ui->btn2->setStyleSheet("background-color:yellow;");
    }else
    {
        ui->btn2->setStyleSheet("background-color:green;");
    }


    num++;
}


//断开按钮对应的槽函数
void Widget::on_btn6_clicked()
{
    disconnect(btn3, SIGNAL(pressed()), ui->btn1, SLOT(hide()));

    disconnect(ui->btn4, &QPushButton::clicked, this, &Widget::my_slot);

    //发射自定义的信号
    emit my_signal();
}

7.信号函数与槽函数参数个数总结

1、信号函数和槽函数进行链接时,一般要求信号函数和槽函数的参数保持一致
connect(信号发送者, SIGNAL(signalFun()),信号接收者, SLOT(slotFun()));     //Ok
connect(信号发送者, SIGNAL(signalFun(int)),信号接收者, SLOT(slotFun(int)));     //Ok
connect(信号发送者, SIGNAL(signalFun(int, char)),信号接收者, SLOT(slotFun(int, char)));     /connect(信号发送者, SIGNAL(signalFun(char, int)),信号接收者, SLOT(slotFun(int, char)));     //False
connect(信号发送者, SIGNAL(signalFun(int)),信号接收者, SLOT(slotFun(char)));     //False
2、当信号函数的参数大于槽函数的参数时
connect(信号发送者, SIGNAL(signalFun(int, char)),信号接收者, SLOT(slotFun()));     //Ok
connect(信号发送者, SIGNAL(signalFun(int, char)),信号接收者, SLOT(slotFun(int)));     //Ok
connect(信号发送者, SIGNAL(signalFun(int, char)),信号接收者, SLOT(slotFun(char)));     //False
3、当信号函数的参数小于槽函数的参数时
connect(信号发送者, SIGNAL(signalFun(int)),信号接收者, SLOT(slotFun(int, char)));     //False
connect(信号发送者, SIGNAL(signalFun(int)),信号接收者, SLOT(slotFun(int, char=0)));     //Ok
#include <QWidget>
#include<QDebug>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE


class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

signals:
    void my_signal();                //自定义信号函数
    void my_signal_1(QString msg);      //自定义带参数的信号函数

public slots:
    void btn1_slot1();       //声明函数
    void btn1_slot2();       //声明函数
    void my_signal_1_slot(QString m = "lallalallalaal");

private slots:
    void on_btn3_clicked();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //1、一个信号可以连接多个槽函数,当信号发射时,所有与之连接的槽函数全部都执行
    connect(ui->btn1, &QPushButton::clicked, this, &Widget::btn1_slot1);
    connect(ui->btn1, &QPushButton::clicked, this, &Widget::btn1_slot2);

    //2、一个槽函数可以连接多个信号
    connect(ui->btn2, &QPushButton::clicked, this, &Widget::btn1_slot1);

    //3、信号函数连接信号函数,表明发射第一个信号后,第二个信号跟着发射
    connect(ui->btn2, &QPushButton::clicked, this, &Widget::my_signal);
    connect(this, &Widget::my_signal, [](){
        qDebug()<<"德玛西亚";
    });

    //4、连接my_signal_1信号到自定义的槽函数中
    connect(this, SIGNAL(my_signal()), this, SLOT(my_signal_1_slot()));

}

Widget::~Widget()
{
    delete ui;
}

//槽函数1的定义
void Widget::btn1_slot1()
{
    qDebug()<<"Good good study";
}
//槽函数2的定义
void Widget::btn1_slot2()
{
    qDebug()<<"day day up";
}

//按钮3发射的信号对应的槽函数
void Widget::on_btn3_clicked()
{
    qDebug()<<"我现在想发射一个my_signal_1信号";

    //emit my_signal_1("hello world");
    emit my_signal();
}
//定义处理my_signal_1的槽函数
void Widget::my_signal_1_slot(QString m)
{
    qDebug()<<"我是处理my_signal_1信号的槽函数:"<<m;
}

8.使用信号与槽完成两个界面的跳转

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

signals:
    void jump();          //自定义跳转函数

private slots:
    void on_jumpBtn_clicked();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

/***********************************第二个界面的头文件*******************/
#ifndef SECOND_H
#define SECOND_H

#include <QWidget>

namespace Ui {
class Second;
}

class Second : public QWidget
{
    Q_OBJECT

public:
    explicit Second(QWidget *parent = nullptr);
    ~Second();

public slots:
    void jump_slot();    //定义有关处理跳转信号的槽函数

private:
    Ui::Second *ui;
};

#endif // SECOND_H
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //信号函数也可以连接信号函数
    //connect(ui->jumpBtn, &QPushButton::clicked, this, &Widget::jump);
}

Widget::~Widget()
{
    delete ui;
}

跳转按钮对应的槽 函数
void Widget::on_jumpBtn_clicked()
{
    //发射跳转信号
    emit jump();

    //关闭当前 界面
    this->hide();
}

/*************************************第二个文件的源文件****************/
#include "second.h"
#include "ui_second.h"

Second::Second(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Second)
{
    ui->setupUi(this);
}

Second::~Second()
{
    delete ui;
}

//处理跳转信号函数对应的槽函数
void Second::jump_slot()
{
    this->show();          //将当前界面进行展示
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值