Qt信号槽之connect介绍(上)

news2024/12/25 9:03:26

关于Qt信号槽中connect与disconnect介绍

首先我们要知道,如果想要使用Qt中的信号槽机制, 那么必须继承QObject类,因为QObject类中包含了信号槽的一系列操作,今天我们来讲解的是信号与槽怎么建立连接以及断开连接

一、connect

QMetaObject::Connection QObject::connect(param p1, param p2, …);

Qt中关于信号槽的connect给出了五种方式,不同connect方法的主要区别是参数的个数及参数类型不同,用来满足不同的场景,但相同的是他们的返回值Connection类型,关于Connection在上一篇文章中也已经描述过,主要用于表示当前信号与当前槽函数连接的句柄,可以通过这个句柄来判断当前连接是否成功、也可以通过此句柄来定位到当时的连接,以此来断开对应信号与槽的连接。


下面分别来讲解这几种不同方式的用法。

1.1 Qt4中通常写法

connect(const QObject *sender, const char * signal, const QObject *receiver, const char * method , Qt::ConnectionType type = Qt::AutoConnection)

// 示例(输入框文字变动实时显示到Label上); 
QLabel *label = new QLabel;
QLineEdit *lineEdit = new QLineEdit;
QObject::connect(lineEdit, SIGNAL(textChanged(const QString&)),
	label, SLOT(setText(const QString&)));

用法:
此方式是Qt4中通用使用的方式,参数分别为信号发送的对象,信号函数,信号接收对象,信号触发的槽函数,这种写法就必须要求给==信号和槽函数前加上宏SIGNAL()和SLOT()==来指定,且信号和槽函数后面必须且只需要加上参数类型(如果没有参数,为空就好,如果有参数,切记只需要填每个参数的类型,不需要具体的变量名称,否则连接失败),因为我们看到此方式信号和槽函数对应的参数类型为 const char*,你可以随意填任意的字符串,但我们必须要按照这种方式,Qt内部会根据宏展开具体的操作,所以这种方式Qt不会帮你检查是否填写错误,尽管你随便填也可以编译成功,只不过连接不上罢了,因为参数都是字符串,编译期是不检查字符串是否匹配,所以这种方式你必须自己检查宏SIGNAL()和SLOT()里面的内容是否正确。

SIGNAL()和SLOT()宏,它们会将信号/槽函数及其参数转化为const char *类型。

使用场景:
此方式用于Qt4的项目中,Qt5为了兼容Qt4保留了此方式,此外因为很多落后且还在更新的项目仍在采用Qt4版本的库,同时由于团队合作的方式,有些人习惯于Qt4的写法,有些人则偏向于Qt5,所以项目中正常这两种方式都会存在。

这种方式其实我们在上篇文章中与Qt5的正常connect方式做了对比,使用过程中需要注意SIGNAL()和SLOT()里面的内容是否正确,而且就算出错编译器也不会报错,所以会经常出现信号槽连接失败的问题。


1.2 Qt4中不常用法

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

等同于

connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)

区别在于这里的信号和槽函数为 const QMetaMethod & 类型,QMetaMethod 是Qt提供的一个专门的类型,可以用于获取一个对象成员函数的元数据,可以获取此成员函数的类型(普通成员函数/信号/槽函数/构造函数)、签名(类似"setValue(double)"),参数类型,参数名称,返回类型,访问权限等等。
正常情况很少用到,大家可能也没有怎么接触过这种方法,这里大家可以认为等同于上面的方式,也就是使用QMetaMethod对信号/槽函数进行指定。
这种方式其实也是为了兼容Qt4中的写法,日常大家可以跳过这种方式。

下面给大家举个例子:

QMetaMethod signalMethod = QMetaMethod::fromSignal(&MyWgtA::signalA);
int methodIndex = m_wgtB->metaObject()->indexOfMethod("onSlotB()");
// 防止找不到;
if (methodIndex != -1)
{
	QMetaMethod slotMethod = m_wgtB->metaObject()->method(methodIndex);
    connect(m_wgtA, signalMethod, m_wgtB, slotMethod);
}

// delete;
QMetaMethod参考
https://blog.csdn.net/qq_21291397/article/details/104774421


1.3 Qt4中信号接收对象省略法

connect(const QObject *sender, const char *signal, const char *method, Qt::ConnectionType type = Qt::AutoConnection) const

等同于

connect(sender, signal, this, method, type)

此种方法在调用过程中省略了信号接收的对象指针,默认为this(调用对象本身),也就是在哪个类里面调用connect,就是连接这个类的信号/槽函数。
如下方代码中,MyWgtA类的signalA(QString)信号与MyTestWgt类的槽函数onSlotTest()进行连接。

void MyTestWgt::initConnections()
{
    connect(m_wgtA, SIGNAL(signalA(QString)), SLOT(onSlotTest()));
}

1.4 Qt5通常用法

connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType type = Qt::AutoConnection)

// 示例(输入框文字变动实时显示到Label上); 
QLabel *label = new QLabel;
QLineEdit *lineEdit = new QLineEdit;
QObject::connect(lineEdit, &QLineEdit::textChanged,
               label,  &QLabel::setText);

参数中的信号必须在头文件中使用signals显示声明,槽函数可以是任何一个成员函数(如果是外部触发必须是public权限),不需要进行slots显示声明(Qt4中必须得有),所以Qt5这种方式真的方便了很多,上一篇文章中,在给大家分析信号槽连接失败原因的时候,就提到Qt4与Qt5的区别,相信大家看完那篇文章也深有体会。

使用这种方式,connect中可以省略信号和槽的参数,也不需要 SIGNAL()和SLOT() 宏的加持,同时编译的时候也会帮你检查信号和槽函数的参数是否正确(保证信号的参数个数>=槽函数参数的个数,且前置参数类型保持一致),防止程序运行的时候才发现信号槽没连上,这个时候你可能写了一大段代码(包含多个connect连接),还不知道是哪个connect会失败,所以建议使用Qt5的信号槽连接方式。

注意:

使用Qt5这种方式,大家有一点是需要注意,也区别于Qt4,当我们的信号重载的时候,需要配合QOverlord进行使用。

![在这里插入图片描述](https://img-blog.csdnimg.cn/cc894a5fe84846ebb8d4a431aa9f330f.png

我们看到QButtonGroup类的buttonClicked信号是有两个重载的,且参数类型不一样,所以我们在使用的时候需要借助QOverload来指定你是用哪一个信号,可以看到下方的代码,这里的代码是信号发生了重载,如果是槽函数发生了重载,同样需要使用QOverload来指定,确保唯一性。

// 如果参数类型是int;
void MyWidget::onBtnClicked(int btnId)
{}

connect(buttonGroup, QOverload<int>::of(&QButtonGroup::buttonClicked), myWidget, &MyWidget::onBtnClicked);
// 如果参数类型是QAbstractButton*;
void MyWidget::onBtnClicked(QAbstractButton* pBtn)
{}

connect(buttonGroup, QOverload<QAbstractButton *>::of(&QButtonGroup::buttonClicked), myWidget, &MyWidget::onBtnClicked);
      

1.5 Qt5信号直连法

connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)

这种方式较为简单,我称之为信号直连法,这里不需要接收信号的对象,我们看到这里只有三个参数,且第三个参数是一个仿函数,相当于信号发出后直接调用仿函数。

A function can be connected to a given signal if the signal has at least as many argument as the slot. A functor can be connected to a signal if they have exactly the same number of arguments.

The connection will automatically disconnect if the sender is destroyed. However, you should take care that any objects used within the functor are still alive when the signal is emitted.

这里提供了两种方式:

a:仿函数

void someFunction()
{
    // todo;
}

QPushButton *button = new QPushButton;
QObject::connect(button, &QPushButton::clicked, someFunction);

b:Lambda表达式

QPushButton *button = new QPushButton;
QObject::connect(button, &QPushButton::clicked, [=](){
    // todo;
});

1.6 Qt5信号直连法2

connect(const QObject *sender, PointerToMemberFunction signal, const QObject *context, Functor functor, Qt::ConnectionType type = Qt::AutoConnection)

此种用法基本和上面的类似,区别在于此方法有了Qt::ConnectionType参数,可以决定当前槽函数的执行方式。

这里也提供了两种方式:

a:仿函数

void someFunction()
{
    // todo;
}

QPushButton *button = new QPushButton;
QObject::connect(button, &QPushButton::clicked, this, someFunction);

b:Lambda表达式

QPushButton *button = new QPushButton;
QObject::connect(button, &QPushButton::clicked, this, [=](){
    // todo;
});

二、disconnect

上面讲解了信号槽的6种连接方式,现在讲讲断开连接的方法 disconnect
一般我们用的比较多的是信号槽的连接,断开可能用的相对少,有的初学者可能还不知道有disconnect这个方法,以为信号槽连接就完事了,就比如一个按钮点击就是需要触发一个方法来完成一系列的操作,如果你把他断开连接了,那这个按钮不是没用了吗,那不一定哦。正常情况下,我们的信号会和一个槽函数绑定,但是Qt允许一个信号可以绑定多个槽函数,当我们想断开其中一个连接的时候就需要使用disconnect去断开这一个,其他几个连接可以保持正常,当然也可以全部断开。

举个例子哈,比如我们给好友发消息,信号是发送按钮点击这个信号(signalSendBtnClicked),这个信号我们需要做两个操作(也就是一个信号对应两个槽函数),一个是将发送的文字显示到我们的聊天窗口,一个是将内容发送给服务器进行转发,正常情况下是做这样两个操作。
情况一:如果对方断线,那我们只需要把内容显示到我们的界面上,但是不需要发送到服务器,所以这里就需要断开一个槽函数。
情况二:如果我们自己断线了,我们实际上什么也做不了,因为你已经离线了,所以点击发送就无需做任何操作,我们就断开所有对应的槽函数即可。

disconnect 方法相对connect简单一些,操作起来也非常方便灵活,Qt提供了几种方式供我们使用.
需要注意的是connect方法都是静态方法,直接调用即可;而disconnect分为静态方法和成员方法两种调用方式(静态方法我会在前方加上 [static])。

disconnect 方法的返回值是一个bool类型,我们可以根据这个值来判断当前是否成功断开信号槽的连接。


1.1 对应Qt4的通用写法(静态方法)

[static] bool QObject::disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)

a、断开对象A的信号signalA()与对象B的槽函数onSlotB()的连接(正常情况下)

connect怎么写的,disconnect就怎么写,即把之前的connect直接换成disconnect。

// 信号槽连接;
connect(lineEdit, SIGNAL(textChanged(const QString&)),
	label, SLOT(setText(const QString&)));

// 信号槽断开;
bool isSuccess = disconnect(lineEdit, SIGNAL(textChanged(const QString&)),
	label, SLOT(setText(const QString&)));

// 根据返回值判断断开是否成功;	
if(isSuccess)	
{
    qDebug() << "disconnect Success";
}

b、断开对象A所有信号的连接:

只需要填写对象A,其他都默认填写nullptr即可断开此对象所有信号的相关连接。

disconnect(myObjectA, nullptr, nullptr, nullptr);

等价于:

// 成员方法(对应下方1.5);
myObjectA->disconnect();

c、断开对象A的信号signalA()所有的连接:

disconnect(myObjectA, SIGNAL(signalA()), nullptr, nullptr);

等价于:

// 成员方法(对应下方1.5);
myObjectA>disconnect(SIGNAL(signalA()));

d、断开对象A与对象B所有的信号槽连接:

disconnect(myObjectA, nullptr, myReceiverB, nullptr);

等价于:

// 成员方法(对应下方1.6);
myObjectA->disconnect(myReceiverB);

关于此方法中的参数,我们可以通过空指针nullptr来充当通配符,但是sender参数必须非空,因为disconnect只能断开某一个对象相关信号的连接,具体就是上述四种用法。

1.2 对应Qt4的不常用法-QMetaMethod(静态方法)

[static] bool QObject::disconnect(const QObject *sender, const QMetaMethod &signal, const QObject *receiver, const QMetaMethod &method)

此方式就是通过对应信号和槽函数的QMetaMethod来断开对应的连接,这里就不举例说明了,不推荐这种方法。

1.3 connect返回句柄断开法(静态方法)

[static] bool QObject::disconnect(const QMetaObject::Connection &connection)

这种方式需要记录之前信号槽连接的句柄,然后通过此句柄来断开唯一对应的信号与唯一对应的槽函数的连接,也不是很推荐。

m_pBtn = new QToolButton;
// 得到句柄;
QMetaObject::Connection cc = connect(m_pBtn, SIGNAL(clicked()), this, SLOT(onBtnCLicked()));

// 根据connect返回的句柄断开相应的信号槽连接;
disconnect(cc);

1.4 对应Qt5的通用写法(静态方法)

[static] bool QObject::disconnect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method)

QObject::disconnect(lineEdit, &QLineEdit::textChanged,
                   label,  &QLabel::setText);

这个方式跟1.1基本一致,也是四种写法,可以使用空指针nullptr来充当通配符,就是注意将参数 const char*换成PointerToMemberFunction 类型即可。
即:

SIGNAL(textChanged(const QString&) 换成 &QLineEdit::textChanged
SLOT(setText(const QString&) 换成 &QLabel::setText)

1.5 断开某个对象的信号连接(成员方法)

bool QObject::disconnect(const char *signal = nullptr, const QObject *receiver = nullptr, const char *method = nullptr) const

与1.1类似,也有四种写法。

// a、断开对象A所有信号的连接:
myObjectA->disconnect();

// b、断开对象A的信号signalA()所有的连接:
myObjectA->disconnect(SIGNAL(mySignal()));

// c、对象A与对象B断开所有信号连接:
myObjectA->disconnect(nullptr, myReceiverB, nullptr);

// d、对象A与对象B断开槽函数onSlotB()所有相关信号的连接::
myObjectA->disconnect(nullptr, myReceiverB, SLOT(onSlotB()));

1.6 对象A与对象B断开相关信号的连接(成员方法)

bool QObject::disconnect(const QObject *receiver, const char *method = nullptr) const

与1.5方法有有类似的效果。

// a、对象A与对象B断开所有信号连接:
myObjectA->disconnect(myReceiverB)


// b、对象A与对象B断开槽函数onSlotB()所有相关信号的连接::
myObjectA->disconnect(myReceiverB, SLOT(onSlotB()));

1.7 注意

如果之前信号连接的是仿函数或者Lambda表达式,我们只能使用1.3里面提到的 QMetaObject::Connection 这种方式来断开连接,因为其他方式没有办法进行唯一匹配。


三、信号槽连接注意点

1、一个信号可以连接一个信号;

connect(myObjectA, &ObjectA::signalA, myReceiverB, &ObjectB::signalB);

2、一个信号可以同时连接多个信号/槽函数;

connect(myObjectA, &ObjectA::signalA, myReceiverB, &ObjectB::signalB);
connect(myObjectA, &ObjectA::signalA, myReceiverB, &ObjectB::onSlotB);
connect(myObjectA, &ObjectA::signalA, myReceiverC, &ObjectC::onSlotC);
connect(myObjectA, &ObjectA::signalA, myReceiverD, &ObjectD::onSlotD);

3、多个信号可以连接一个槽函数;

connect(myObjectA, &ObjectA::signalA, myReceiverD, &ObjectD::onSlotD);
connect(myObjectB, &ObjectB:signalB, myReceiverD, &ObjectD::onSlotD);
connect(myObjectC, &ObjectC::signalC, myReceiverD, &ObjectD::onSlotD);

4、如果一个信号连接多个信号/槽函数,那么绑定的信号/槽函数被触发的顺序与建立连接的顺序一致;

connect(myObjectA, &ObjectA::signalA, myReceiverB, &ObjectB::onSlotB);
connect(myObjectA, &ObjectA::signalA, myReceiverC, &ObjectC::onSlotC);
connect(myObjectA, &ObjectA::signalA, myReceiverD, &ObjectD::onSlotD);

emit myObjectA->signalA();
// 发送信号signalA,槽函数执行顺序onSlotB() -> onSlotC() -> onSlotD();

5、正常情况下,如果一个连接被调用两次(多次),则该信号对应的信号/槽函数会被触发两次(多次);

void ObjectB::onSlotB()
{
    qDebug() << "Run slotB";
}

connect(myObjectA, &ObjectA::signalA, myReceiverB, &ObjectB::onSlotB);
connect(myObjectA, &ObjectA::signalA, myReceiverB, &ObjectB::onSlotB);
connect(myObjectA, &ObjectA::signalA, myReceiverB, &ObjectB::onSlotB);

emit myObjectA->signalA();

// 调用三次输出三次;
Run slotB
Run slotB
Run slotB

6、特殊情况下,如果connect方法中的参数Qt::ConnectionType type = Qt::UniqueConnection,那么表示此次的连接是唯一的,建立过连接之后,再次调用同样的代码建立连接将以失败而告终,也就是只能connect成功一次,后面的connect将失效。

以下代码connect调用了四次,但是失败两次,因为connect中有三次参数 ConnectionType类型为Qt::UniqueConnection,所以只成功了一次,故信号触发,槽函数会被执行两次。

void ObjectB::onSlotB()
{
    qDebug() << "Run slotB";
}

// isSucces = true; (第一次调用,所以返回true)
isSucces = connect(myObjectA, &ObjectA::signalA, myReceiverB, &ObjectB::onSlotB, Qt::UniqueConnection);
// isSucces = false; (第二次调用,且ConnectionType 仍然为 Qt::UniqueConnection)
isSucces = connect(myObjectA, &ObjectA::signalA, myReceiverB, &ObjectB::onSlotB, Qt::UniqueConnection);
// isSucces = false; (第三次调用,且ConnectionType 仍然为 Qt::UniqueConnection)
isSucces = connect(myObjectA, &ObjectA::signalA, myReceiverB, &ObjectB::onSlotB, Qt::UniqueConnection);

// isSucces = true;(第四次调用,但是ConnectionType 默认为 AutoConnection)
isSucces = connect(myObjectA, &ObjectA::signalA, myReceiverB, &ObjectB::onSlotB);

emit myObjectA->signalA();

// 调用四次输出两次;
Run slotB
Run slotB

需要注意的是Qt::UniqueConnection对lambdas表达式或者非成员函数/仿函数不生效。

7、不管对象A的信号signalA()和对象的槽函数onSlotB()的信号槽连接被调用了一次或者多次(信号触发会一次或多次调用槽函数),只要调用了对应的disconnect方法,那么不管调用的多少次的connect方法,所有的连接都会断开。

void ObjectB::onSlotB()
{
    qDebug() << "Run slotB";
}

connect(myObjectA, &ObjectA::signalA, myReceiverB, &ObjectB::onSlotB);
connect(myObjectA, &ObjectA::signalA, myReceiverB, &ObjectB::onSlotB);
connect(myObjectA, &ObjectA::signalA, myReceiverB, &ObjectB::onSlotB);

disconnect(myObjectA, &ObjectA::signalA, myReceiverB, &ObjectB::onSlotB);

emit myObjectA->signalA();

// 调用三次无输出,因为调用了disconnect,所有的连接都断开;

8、信号槽中信号发送方对象sender或者接收方对象receiver其中一个被销毁connect将会自动断开

void ObjectB::onSlotB()
{
    qDebug() << "Run slotB";
}

myObjectA = new ObjectA;
myReceiverB = new ObjectB;

connect(myObjectA, &ObjectA::signalA, myReceiverB, &ObjectB::onSlotB);

disconnect(myObjectA, &ObjectA::signalA, myReceiverB, &ObjectB::onSlotB);

delete myReceiverB;

emit myObjectA->signalA();

// 无输出,因为对象myReceiverB被销毁;

9、there is an implicit conversion between the types of the corresponding arguments in the signal and the slot
信号和槽中相应参数的类型之间存在隐式转换

class MyWgtA : public QWidget
{
	Q_OBJECT

public:
	MyWgtA(QWidget *parent = nullptr) {};

signals:
	void signalA(double);
};

class MyWgtB : public QWidget
{
	Q_OBJECT

public:
	MyWgtB(QWidget *parent = nullptr) {};

	// 没有明确声明槽函数;
public:
	void onSlotB(int param)
	{
	    qDebug() << param;
	}
};

void test()
{
    MyWgtA* wgtA = new MyWgtA;
    MyWgtB* wgtB = new MyWgtB;
    connect(wgtA, &MyWgtA::signalA, wgtB, &MyWgtB::onSlotB);
    
    emit wgtA->signalA(12.8);
    
    // 输出12;
}

10、关于信号和槽函数自动绑定的问题,对应的槽函数必须写成on_控件名_信号名的格式,这种情况下Qt提供的元对象系统会提供一个机制自动关联相关的信号和槽函数。

下方是Qt源码中给出的解释;

Qt’s meta-object system provides a mechanism to automatically connect
signals and slots between QObject subclasses and their children. As long
as objects are defined with suitable object names, and slots follow a
simple naming convention, this connection can be performed at run-time
by the QMetaObject::connectSlotsByName() function.

如果出现这种情况,我们仍然再次使用connect去绑定这样的信号与槽函数,会输出以下警告:

QMetaObject::connectSlotsByName: No matching signal for slotName

// 待验证;
这里其实跟setupUi有关系,即带ui文件的界面类,因为designer中我们可以去绑定一个信号和槽函数,我们可以去看下ui文件生成的代码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/688871.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在windows server上用Mosquitto软件创建MQTT服务器

今天下午捣鼓了半天&#xff0c;在云服务器上面创建了个MQTT服务器&#xff0c;然后用MQTTX软件进行了测试。过程记录如下&#xff1a; 1、下载mosquitto软件&#xff0c;链接如下图&#xff1a; 2、下载完成后安装&#xff0c;一直点下一步下一步就好了。 3、在安装路径下&am…

快速捡回使用workbench控制mysql创建数据库的基本步凑

首先如果&#xff0c;不想要在原来已经建好的数据库下建立数据表&#xff0c;可以新建数据库。 具体操作步凑如下&#xff1a; 选择后如下所示&#xff1a; 有现成的创建代码的话&#xff0c;就直接复制执行现成的创建代码即可&#xff0c;如果没有现成的创建代码的话&#xff…

Java设计模式之单例模式-【懒汉式与饿汉式】

1、单例&#xff0c;模式 单例模式属于创建型模式的一种&#xff0c;应用于保证一个类仅有一个实例的场景下&#xff0c;并且提供了一个访问它的全局方法 单例模式的特点&#xff1a;从系统启动到终止&#xff0c;整个过程只会产生一个实例。单例模式常用写法&#xff1a;懒汉…

STM32设置为I2C从机模式

STM32设置为I2C从机模式 目录 STM32设置为I2C从机模式前言1 硬件连接2 软件编程3 运行测试3.1 I2C连续写入3.1 I2C连续读取3.1 I2C单次读写测试 4 总结 前言 STM32的I2C作为主机的情况相信很多同学都用过&#xff0c;网上也有很多教程&#xff0c;但是作为从设备使用的例子应该…

【C++ 程序设计】第 9 章:函数模板与类模板

目录 一、函数模板 &#xff08;1&#xff09;函数模板的概念 &#xff08;2&#xff09;函数模板的示例 &#xff08;3&#xff09;函数或函数模板调用语句的匹配顺序 二、类模板 &#xff08;1&#xff09;类模板概念 &#xff08;2&#xff09;类模板示例 &…

阵列模式综合第三部分:深度学习(附源码)

一、前言 这个例子展示了如何设计和训练卷积神经网络&#xff08;CNN&#xff09;来计算产生所需模式的元素权重。 二、介绍 模式合成是阵列处理中的一个重要课题。阵列权重有助于塑造传感器阵列的波束图案&#xff0c;以匹配所需图案。传统上&#xff0c;由于空间信号处理和频…

SSL工作原理

SSL 是一个安全协议&#xff0c;它提供使用 TCP/IP 的通信应用程序间的隐私与完整性。因特网的 超文本传输协议&#xff08;HTTP&#xff09;使用 SSL 来实现安全的通信。 在客户端与服务器间传输的数据是通过使用对称算法&#xff08;如 DES 或 RC4&#xff09;进行加密的。公…

使用ZenDAS进行Gompertz趋势分析

某项目做了18次测试&#xff0c;每次测试发现的缺陷个数如下表所示&#xff1a; 测试序号 发现缺陷数 1 60 2 96 3 157 4 191 5 155 6 106 7 64 8 335 9 92 10 196 11 109 12 133 13 166 14 129 15 16 16 30 17 19 18 5 对上述的数据在Z…

IPv6手工隧道配置与验证实验

IPv6手工隧道配置与验证实验 【实验目的】 熟悉IPv6手工隧道的概念。 掌握IPv6和IPv4共存的实现方法。 掌握IPv6手工隧道的配置。 验证配置。 【实验拓扑】 实验拓扑如下图所示。 实验拓扑 设备参数如表所示。 设备参数表 设备 接口 IPv6地址 子网掩码位数 默认网…

中间件-netty(1)

netty 前言篇 文章目录 一、IO基础篇1.概念1.1 阻塞(Block)和非阻塞(Non-Block)1.2 同步(Synchronization)和异步(Asynchronous)1.3 BIO 与 NIO 对比1.3.1 面向流与面向缓冲1.3.2 阻塞与非阻塞1.3.3 选择器的问世 2.NIO 和 BIO 如何影响应用程序的设计2.1 API调用2.2 数据处理2…

蓝桥杯专题-试题版-【操作格子】【查找整数】【分解质因数】【高精度加法】

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 &#x1f449;关于作者 专注于Android/Unity和各种游…

Spring FrameWork从入门到NB -三级缓存解决循环依赖内幕 (二)

开始用上一篇文章讲到的Spring依赖注入的步骤&#xff0c;用两个例子来推导一下整个过程&#xff0c;举例子有助于了解真相。 先用一个最简单的例子&#xff1a;没有依赖的单例bean的创建。 推导过程是需要上一篇文章的步骤的&#xff0c;要参照步骤一步一步来。 无依赖的单…

Linux内核代码60%都是驱动?驱动代码不会造成内核臃肿吗?

为什么内核中驱动占比最高 一、前言二、Linux中避免内核臃肿的措施2.1 交叉编译及SDK包的裁剪2.2 设备树2.3 模块化2.4 硬件抽象层 三、嵌入式Linux的裁剪四、总结 一、前言 今天逛知乎看到这么一个问题&#xff1a;为什么Linux内核代码60%都是驱动? 如果每支持新的设备就加入…

【设计模式】Java设计模式——模板方法模式(Template Pattern)

文章目录 1. 介绍1.1 定义1.2 作用 2. 模式结构2.1 UML类图2.2 模式组成 3. 代码实例3.1 背景3.2 应用 4. 优点5. 缺点6. 应用场景 1. 介绍 1.1 定义 模板方法模式(Template Pattern)&#xff0c;又叫模板模式&#xff0c;它属于行为型模式模板方法模式定义一个模板结构&…

Apikit 自学日记:版本管理

功能入口&#xff1a;API管理应用 / 选中某个项目 / 项目管理菜单 / 项目版本管理 项目版本管理功能模块提供对项目级别的版本管理&#xff0c;可新增、删除、对比项目级版本。在创建项目版本号的时候会对整个项目的部分模块数据进行快照保存。可用于每次迭代发布打全局版本号…

ESP32设备驱动-TMF8801激光测距传感器驱动

TMF8801激光测距传感器驱动 文章目录 TMF8801激光测距传感器驱动1、TMF8801介绍2、硬件准备3、软件准备4、驱动实现1、TMF8801介绍 TMF8801 是一款真正的直接飞行时间 (ToF) 传感器系统,采用单一模块化封装,通过亚纳秒光脉冲和抗锯齿“秒表”方法测量往返时间,提供高精度深度…

流量分析工具wireshark-学习笔记

&#xff08;一&#xff09;wireshark工具 1、wireshark工具简介 Wireshark是一种开源网络分析工具&#xff0c;它可以让你在计算机网络上捕获和查看数据包&#xff0c;并能帮助你深入了解网络的运行和协议的实现。它可以捕获不同类型的流量&#xff0c;包括以太网、Wi-Fi、TC…

【面试题】面试官问:如果有100个请求,你如何使用Promise控制并发?

大厂面试题分享 面试题库 前后端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 web前端面试题库 VS java后端面试题库大全 开篇 在现代Web开发中&#xff0c;异步请求已经成为了必不可少的一部分。然而&#xff0c;…

ISP之图像降分辨率

1、图像缩放背景 图像的放大、缩小(简称缩放)是图像处理的一种处理方法。所谓图像缩放是指图像分辨率的改变&#xff0c;它在图像显示、传输、图像分析以及动画制作、电影合成、甚至医学图像处理中都有着相当广泛的应用。比如要在1024 X 768 分辨率的显示器上全屏显示800 X 60…

8.2 电压比较器(2)

五、集成电压比较器 1、集成电压比较器的主要特点和分类 电压比较器可将模拟信号转换成二值信号&#xff0c;即只有高电平和低电平两种状态的离散信号。因此&#xff0c;可用电压比较器作为模拟电路和数字电路的接口电路。集成电压比较器虽然比集成运放的开环增益低&#xff…