QT—信号与槽详解

news/2024/7/4 22:03:50 标签: qt, c++, 开发语言

目录

一、什么是信号与槽

二、信号与槽的添加

1.添加槽方法

2.添加信号 

3.发送信号

4.信号与槽连接

三、连接类型

1.一对一

2.一对多

3.多对一

四、信号与槽断开连接 

1.断开一个对象的所有信号关联

2.断开指定信号的所有关联

3.断开指定接收者的所有关联

4.断开指定信号于槽的关联

五、信号与槽机制的优越性


一、什么是信号与槽

    信号与槽(Signal & Slot)是 Qt 编程的基础,也是 Qt 的一大创新。因为有了信号与槽的编程机制,在 Qt 中处理界面各个组件的交互操作时变得更加直观和简单。
    信号(Signal)就是在特定情况下被发射的事件,例如PushButton 最常见的信号就是鼠标单击时发射的 clicked() 信号。发射信号使用Qt的emit关键字。定义信号使用QT的signals关键字

定义信号,如:

signals:
    void testFun(QString& str); //信号不能也无需实现

 发射信号,如:

void fun(){
    QString str="就是这个感觉";
    emit testFun(str);       
}

    槽(Slot)就是对信号响应的函数。槽就是一个函数,与一般的C++函数是一样的,可以声明在类的任何部分(public、private 或 protected),可以具有任何参数,也可以被直接调用。槽函数与一般的函数不同的是:槽函数可以与一个信号关联,当信号被发射时,关联的槽函数被自动执行。 

    声明三个槽方法,如:

private slots:
    void testFun1(QString& str);
    void testFun2();
    void testFun3();

二、信号与槽的添加

1.添加槽方法

1.1通过ui设计页面添加槽方法

在ui设计页面中,右击控件、选解“转到槽”即可添加为控件添加相应的槽方法,并与信号关联

1.2手动添加槽方法 

 按“on_对象名_事件名”的格式手动添加槽方法,按这种格式添加的槽方法可以自动与单击时发射的 clicked() 信号连接。

private slots:
    void on_whBtn_clicked();
    void on_zgBtn_clicked();
    void on_sjBtn_clicked();    //自动连接 on_对象名_信号名

以上两种方式都可以自动的将槽方法与信号连接,但如果是自定义的槽方法则需要使用connect函数连接 

2.添加信号 

 关键字signals定义一个信号,信号不能也无需实现,并且返回值是void,信号与槽方法都可以携带参数,但是槽方法的参数类型必须是信号参数类型保持一致或者少于信号参数

signals:
    void Commeon(QString& str); //信号不能也无需实现,且返回值是void

3.发送信号

 使用emit关键字发送信号 。我们可以在任何地方使用emit关键字发送信号,包括在槽方法内

void MainWindow::on_whBtn_clicked()
{
    QString str="武汉";
    emit Commeon(str);
}

void MainWindow::on_zgBtn_clicked()
{
    QString str="中国";
    emit Commeon(str);
}

void MainWindow::on_sjBtn_clicked()
{
    QString str="世界";
    emit Commeon(str);
}

4.信号与槽连接

在构造函数中,通过connect将信号与定义的槽方法绑定起来 

QMetaObject::Connection QObject::connect(
const QObject *sender, //信号发送者
const char *signal, //发送的信号
const QObject *receiver, //信号接收者
const char *method, //表示与信号连接的方式的字符串,可以是槽或信号
Qt::ConnectionType type = Qt::AutoConnection //连接方式,默认自动连接

)

    常用格式:connect(sender, SIGNAL(signal()), receiver, SLOT(slot()));

    信号使用SIGNAL,对于槽则使用SLOT,用它们将函数的原型包围起来即可。注意connect方法采用SIGNAL()及SLOT()时,这里的函数原型只能写出类型,不能有任何参数名,否则连接将会失败。

    例如

connect(this,SIGNAL(Commeon(QString&)),this,SLOT(CommeonGuys(QString&)));

同时信号与槽连接方式:

  1. Qt::AutoConnection:(默认连接方式)自动方式,由系统自动选择连接方式。
  2. Qt::DirectConnection:直接方式,信号发射时,立即调用槽。
  3. Qt::QueuedConnection:队列方式,信号发射时产生一个事件进入队列,事件被处理时槽才能调用。
  4. Qt::BlockQueuedConnection:阻塞队列方式,信号发射时产生一个事件进入队列,然后当前线程进入阻塞状态,直到事件处理完毕,若接收方位于发送信号的线程中,则程序会死锁,故此连接方式仅用于多线程。

 也可以不使用SIGNAL和SLOT,直接信号和槽的地址。

connect(this,&MainWindow::Common,this,&MainWindow::CommonGuys);

    信号可以看做是特殊的函数,需要带括号,可带参数,信号无需实现也不能实现。槽函数需要带括号,有参数时还需要指明参数。当信号和槽函数带有参数时,在 connect()函数里,要写明参数的类型。信号的参数需与槽的参数列表一致,允许比槽参数多。如果不匹配或参数过少,会出现编译错误或运行错误。在使用信号与槽的类中,必须在类的定义中加入宏 Q_OBJECT。当一个信号被发射时,与其关联的槽函数通常被立即执行,就像正常调用一个函数一样。只有当信号关联的所有槽函数执行完毕后,才会执行发射信号处后面的代码。 

三、连接类型

1.一对一

声明两个信号signal1、signal2 和一个槽方法slot( ),将信号signal1与信号signal2相连,信号signal2与槽方法slot( )相连

signals:
    void signal1();
    void signal2();
private slots:
    void slot();

槽方法实现

void MainWindow::slot()
{
    qDebug()<<"我爱QT编程";
}

在构造函数中将信号与信号,信号与槽方法相连

connect(this,SIGNAL(signal1()),this,SIGNAL(signal2()));
connect(this,SIGNAL(signal2()),this,SLOT(slot()));

当发送signal1时,运行结果

2.一对多

声明一个信号和多个槽方法 

signals:
    void comeon(QString&str);
private slots:
    void comeon1();
    void comeon2();
    void comeon3();

槽方法实现 

void MainWindow::comeon1()
{
    qDebug()<<"我爱编程";
}

void MainWindow::comeon2()
{
    qDebug()<<"我爱QT";
}

void MainWindow::comeon3()
{
    qDebug()<<"我爱QT编程";
}

在构造函数中将信号与槽方法连接

connect(this,SIGNAL(comeon(QString&)),this,SLOT(comeon1()));
connect(this,SIGNAL(comeon(QString&)),this,SLOT(comeon2()));
connect(this,SIGNAL(comeon(QString&)),this,SLOT(comeon3()));

运行结果

3.多对一

声明多个信号和一个槽方法

signals:
    void come1(QString& str);
    void come2(QString& str);
    void come3(QString& str);
private slots:
    void come(QString& str);

槽方法实现

void Dialog::come(QString& str)
{
    qDebug()<<str;
}

准备三个控件,每个控件的槽方法各发送一个信号

void Dialog::on_Btn1_clicked()
{
    QString str="我爱编程";
    emit come1(str);
}

void Dialog::on_Btn2_clicked()
{
    QString str="我爱QT";
    emit come2(str);
}

void Dialog::on_Btn3_clicked()
{
    QString str="我爱QT编程";
    emit come3(str);
}

在构造函数中连接信号与槽方法

connect(this,SIGNAL(come1(QString&)),this,SLOT(come(QString&)));
connect(this,SIGNAL(come2(QString&)),this,SLOT(come(QString&)));
connect(this,SIGNAL(come3(QString&)),this,SLOT(come(QString&)));

当点击不同按键时,执行结果

四、信号与槽断开连接 

QObject::disconnect(
    const QObject* sender,
    const char* signal,
    const QObject *receiver,
    const char* method
);

1.断开一个对象的所有信号关联

disconnect(sender,0,0,0);
//等价于
sender->disconnect();

2.断开指定信号的所有关联

disconnect(sender,SIGNAL(signal()),0,0);
//等价于
sender->disconnect(SIGNAL(signal()));

3.断开指定接收者的所有关联

disconnect(sender,0,receiver,0);
//等价于
sender->disconnect(SIGNAL(signal()));

4.断开指定信号于槽的关联

disconnect(sender, SIGNAL(single1()), receiver, SLOT(slotFun())); 
//等价于:
disconnect(myConnection);	//myConnection为connect()的返回值

myConnection是使用connect函数时的返回值,可以先用一个变量保存这个返回值。

例如添加m_res变量用于保存connect( ) 返回值 

private:
    QMetaObject::Connect m_res;

使用connect时保存返回值

m_res = connect(this,SIGNAL(signal()),this,SLOT(slot()));

断开连接

disconnect(m_res);

五、信号与槽机制的优越性

  1. 信号与槽机制是类型安全的,相关联的信号与槽参数必须匹配
  2. 信号与槽是松耦合的,信号发送者不知道也不需知道接受者的信息。
  3. 信号与槽可以使用任意类型的任意数量的参数。

http://www.niftyadmin.cn/n/1662887.html

相关文章

python之Flask实现登录功能

网站少不了要和数据库打交道&#xff0c;归根到底都是一些增删改查操作&#xff0c;这里做一个简单的用户登录功能来学习一下Flask如何操作MySQL。 用到的一些知识点&#xff1a;Flask-SQLAlchemy、Flask-Login、Flask-WTF、PyMySQL这里通过一个完整的登录实例来介绍&#xff0…

【TensorFlow学习笔记】4:认识Variable及其重用(共享),在scope上的初始化

学习《深度学习之TensorFlow》时的一些实践。 认识TF中的Variable TF通过name来标识变量(Variable)&#xff0c;这和调用者定义的程序里的"变量名"无关。当不指定name时&#xff0c;由TF自己指定&#xff0c;当创建的变量的name已经存在时&#xff0c;TF会为其改名。…

LINUX网络服务01:DHCP

第一步&#xff1a;安装rpm -ivh /mnt/Packages/dhcp-4.2.5-58.el7.centos.x86_64.rpm第二步&#xff1a;修改配置文件rpm -qc dhcpvi /etc/dhcp/dhcpd.conf 查看dhcp服务相关的配置文件subnet 192.168.80.0 netmask 255.255.255.0 {range 192.168.80.100 192.168.80.200;optio…

QT—动态属性系统

目录 一、创建动态属性 二、Q_PROPERTY宏参数类型 三、演示 四、通过基类读写动态属性 1.读属性 2.改属性 一、创建动态属性 在标准C中&#xff0c;为了保证封装性&#xff0c;我们经常声明一个私有变量&#xff0c;然后声明两个公有函数&#xff0c;即set函数和get函…

Python中列表并不是首选,其他序列类型介绍:数组、内存视图、NumPy 、双向队列deque

数组array.array 比如我们要存放100万个浮点数的话&#xff0c;使用数组就会更高效一点&#xff0c;因为数组背后存储是不是float对象&#xff0c;而是数字对应的机器翻译&#xff0c;也就是字节表述。 数组支持所有可变序列的操作&#xff0c;比如.pop .insert .extend。另外…

【TensorFlow学习笔记】5:variable_scope和name_scope,图的基本操作

学习《深度学习之TensorFlow》时的一些实践。 variable_scope 一般的嵌套 上节有学到在嵌套scope中的变量&#xff0c;一般是&#xff1a; import tensorflow as tf# with tf.variable_scope("scopeA") as spA: # var1 tf.get_variable("v1", [1])…

WPF中的资源(二) - 二进制资源

原文:WPF中的资源&#xff08;二&#xff09; - 二进制资源WPF中的二进制资源&#xff0c;就是类似于MFC中在对话框程序中添加的图片、字符串等资源&#xff0c;程序在运行时将其转换成二进制&#xff0c;以供程序使用。下面以将字符串转换成二进制为例来说明&#xff0c;二进制…

【Vue.js学习笔记】3:数据绑定,事件绑定

数据绑定 使用Vue时在Vue对象的el字段中要指定一下根容器&#xff0c;这里用id选择器。这个例子同时学习了data和methods的基本用法。 数据绑定&#xff08;data-binding&#xff09;可以将Vue对象中的data的值绑定到HTML标签中的某些位置&#xff0c;则修改时只需要修改对象…