QT笔记9__信号与槽

版权声明:本文为博主原创文章, 欢迎转载,转载请注明出处。 https://blog.csdn.net/baicaidiaozhui/article/details/87337362

一、信号与槽简介

1、基本介绍

信号与槽机制是Qt的核心特征,也是Qt不同于其他开发框架的最突出特征,该机制主要实现Qt中两个对象之间的通信。
信号与槽之间的关联可以实现:

一个信号关联一个槽;
一个信号关联多个槽;
多个信号关联一个槽;
信号关联信号;

2、信号

  • 1、采用关键字signals声明一个信号,前面不能用public、private、protected等限定符,信号默认是public,表明信号可以在任何地方发射,但建议只在该类和子类中发射该信号;

  • 2、信号只需要声明,不需要定义;

  • 3、信号没有返回值,返回类型只能是void,但信号可以传递参数;

  • 4、只有QObject类及其子类才能采用信号与槽机制,且需要在类声明中添加Q_OBJECT宏;

  • 5、发射信号采用emit 关键字;

信号声明,例:

>signals :
	void landownerSignal(int number);
	void brownTwoSignal(QString str);
	void brownBigSignal();

信号发射,例:

1、带int参数
emit landownerSignal(4);

2、带QString类型参数
QString str = QString::fromLocal8Bit(“我熊二,飞机带翅膀!”);
emit brownTwoSignal(str);

3、不带参数
emit brownBigSignal();

3、槽

  • 槽函数需要用slots关键字修饰,可以是public slots、private slots、protected slots也可以是虚函数,在Qt5中cao还可以直接是一般的普通的成员函数,无需slots修饰;

例:

public:
	void landowner(int card);

public slots:
void on_pushButton_brownTwo_clicked();
void on_pushButton_brownBig_clicked();
void on_pushButton_landowner_clicked();
//
void brownTwo(QString card); 
void brownBig();

二、信号与槽的三种连接方式

在Qt5中信号与槽有三种关联形式。

1、采用传统的connnect()函数

QObject类中的connect()函数原型如下:

static QMetaObject::Connection connect(const QObject *sender, const char *signal,
const QObject *receiver, const char *member, Qt::ConnectionType = Qt::AutoConnection);

sender,发射信号的对象;
signal,要发射的信号,使用SIGNAL()宏;
receiver,接受信号的对象;
method,执行的槽函数;使用SLOT()宏;
Qt::AutoConnection,表示默认关联方式为自动关联
使用这类connect()重载函数时,槽函数必须采用添加关键slots进行声明的槽函数;
例:

>	connect(this, SIGNAL(brownTwoSignal(QString)), this, SLOT(brownTwo(QString )));
  • 注意:以上信号与槽的使用例子中,可进行QString类型的参数传递,但要注意的是槽函数的参数数目必须小于等于信号的参数

2、Qt5中的connnect()重载函数

Qt5中新增的connect重载函数原型如下:

static QMetaObject::Connection connect(const QObject *sender, const QMetaMethod &signal,
const QObject *receiver, const QMetaMethod &method,
Qt::ConnectionType type = Qt::AutoConnection);

由上可知,这种重载方式与第一种的区别在于:signal和method两个参数的类型由原来的const char*类型变为了函数指针

因此,信号与槽不必再采用SIGNAL()和SOLT()的形式,槽函数也不必采用slots关键字声明,满足参数要求的成员函数即可。
例:

 	connect(this, &QtSlotLearn::landownerSignal, this, &QtSlotLearn::landowner);
  • 这种使用方式,可以在编译过程中进行检查,能够避免了无法发现的拼写错误、参数不符错误,一般推荐采用该方式进行关联;

3、信号与槽的自动连接方式

信号与槽的自动关联方式,一般是针对控件的内部信号而言。通过特定格式来命名槽函数,即可实现信号与槽的自动关联;

  • 格式
    ** on_ + 控件名_ + 信号
  • 示例
public slots:
void on_pushButton_brownTwo_clicked();
//控件名为pushButton_brownTwo,信号为clicked();

说明: 当点击名为“”pushButton_brownTwo“”的按钮时,自动发射clicked()信号,且该信号会自动关联到槽函数 on_pushButton_brownTwo_clicked()上;

  • 限制条件
    这种自动关联信号与槽的方式非常简洁,小码哥在用QtDesigner写界面的时候喜欢用这种自动关联的形式来进行槽与信号的连接,但这种自动关联的方式也有一些限制;
    1、需要调用connectSlotsByName()函数来支持信号与槽的自动关联;

    2、需要使用setObjectName()来指定控件名,其控件命名需在connectSlotsByName()函数之前实现;

    3、一般在setupUi()函数中已经调用了connectSlotsByName()函数,如果需要对手动代码添加的控件进行信号槽的自动关联,采用setObjectName()指定控件名应该在setupUi()函数之前

这里小码哥建议,如果你是利用代码添加的控件,要实现信号与槽,就直接采用connect,简单明了也省心;
如果是QtDesigner界面上添加的部件,且部件的内置信号满足你都需要,则可以直接使用自动关联方式;
控件的内置信号,QtDesigner上可以很容易找到;
pushButton内置信号如下:

在这里插入图片描述

三、案例

以下小码哥给出一个案例,该案例中包含了三种信号与槽的关联方式;
头文件:QtSlotLearn.h

#pragma once

#include <QtWidgets/QMainWindow>
#include "ui_QtSlotLearn.h"

class QtSlotLearn : public QMainWindow
{
	Q_OBJECT
public:
	QtSlotLearn(QWidget *parent = Q_NULLPTR);
private:
	Ui::QtSlotLearnClass ui;
public:
	//一般成员函数
	void landowner(int card);
public slots:
	//自动关联槽
	void on_pushButton_brownTwo_clicked();
	void on_pushButton_brownBig_clicked();
	void on_pushButton_landowner_clicked();
	//槽
	void brownTwo(QString card); 
	void brownBig();
signals :
	//各种传参和不传参的信号
	void landownerSignal(int number);
	void brownTwoSignal(QString str);
	void brownBigSignal();
};

QtSlotLearn.cpp 文件;

#include "QtSlotLearn.h"
#include <QLabel>

QtSlotLearn::QtSlotLearn(QWidget *parent)
	: QMainWindow(parent)
{
	ui.setupUi(this);
	ui.pushButton_brownTwo->setEnabled(true);
	ui.pushButton_brownBig->setEnabled(false);
	ui.pushButton_landowner->setEnabled(false);
	this->setWindowTitle(QString::fromLocal8Bit("熊熊斗地主"));

	connect(this, SIGNAL(brownTwoSignal(QString)), this, SLOT(brownTwo(QString )));
	connect(this, &QtSlotLearn::landownerSignal, this, &QtSlotLearn::landowner);
	connect(this, SIGNAL(brownBigSignal()), this, SLOT(brownBig()));

}

//***********自动连接处理此刻的clicked()信号槽函数:
//该函数自动连接控件pushButton_brownTwo的clicked()信号
void QtSlotLearn::on_pushButton_brownTwo_clicked()
{
	QString str = QString::fromLocal8Bit("我熊二,飞机带翅膀!");
	emit brownTwoSignal(str);
}

//该函数自动连接控件pushButton_brownBig的clicked()信号
void QtSlotLearn::on_pushButton_brownBig_clicked()
{
	emit brownBigSignal();
}

//该函数自动连接控件pushButton_landowner的clicked()信号
void QtSlotLearn::on_pushButton_landowner_clicked()
{
	emit landownerSignal(4);
}

//***********利用connect()函数手动链接的槽函数;
void QtSlotLearn::brownTwo(QString card)
{
	//添加QLabel显示文字
	QLabel* labelTemp = new QLabel(ui.frame);
	labelTemp->setText(card);
	labelTemp->move(50,50);
	labelTemp->show();
	//下家出牌,设置按钮是否可用;
	ui.pushButton_brownTwo->setEnabled(false);
	ui.pushButton_brownBig->setEnabled(false);
	ui.pushButton_landowner->setEnabled(true);
}

void QtSlotLearn::brownBig()
{	
	//设置显示文字
	QString str = QString::fromLocal8Bit("光头强敢欺负熊二,看我双王!");
	//添加QLabel显示文字
	QLabel* labelTemp = new QLabel(ui.frame);
	labelTemp->setText(str);
	labelTemp->move(200, 100);
	labelTemp->show();
	//下家出牌,设置按钮是否可用;
	ui.pushButton_brownTwo->setEnabled(true);
	ui.pushButton_brownBig->setEnabled(false);
	ui.pushButton_landowner->setEnabled(false);
}

//***********非槽函数的成员函数:
void QtSlotLearn::landowner(int card)
{
	//设置显示文字
	QString str = QString::fromLocal8Bit("嘿嘿,小熊熊,看强哥我") + QString::number(card) + QString::fromLocal8Bit("个二,灭了你");
	//添加QLabel显示文字
	QLabel* labelTemp = new QLabel(ui.frame);
	labelTemp->setText(str);
	labelTemp->move(100, 300);
	labelTemp->show();
	//下家出牌,设置按钮是否可用;
	ui.pushButton_brownTwo->setEnabled(false);
	ui.pushButton_brownBig->setEnabled(true);
	ui.pushButton_landowner->setEnabled(false);
}

以上代码实现一段熊出没中斗地主的情景(小码哥深受熊出没的毒害^_^!)。

击当前玩家按钮,发射clicked()信号,调用对应槽函数来实现激活下一个玩家按钮,并打出手中的牌的功能;

打牌的次序:熊二——>光头强——>熊大!

实现效果如下:
在这里插入图片描述

信号与槽的机制非常灵活便捷,但是在使用的时候一定要注意以上提及的一些细节,稍稍错过一些细节,这种机制就很容易失效!

四、参考资料

1、《Qt Creator快速入门》

猜你喜欢

转载自blog.csdn.net/baicaidiaozhui/article/details/87337362