【C++】 Qt-信号与槽

news2024/11/24 1:09:56

文章目录

      • 基本概念
      • 添加信号与槽
        • 方法一
        • 方法二
      • 自定义信号与槽
        • CheckBox
        • 自定义QMessageBox
        • 自定义信号
      • 信号与槽多对多
        • 一个信号连接多个槽
        • 多个信号连接一个槽
        • 一个信号连接一个信号连接一个槽
      • 断开连接
        • 方法一
        • 方法二
        • 判断是否连接成功

基本概念

信号(signal)和槽(slot)是Qt框架引以为豪的机制之一,用于完成界面操作的响应,是完成任意两个Qt对象之间的通信机制。

信号:特定条件下发射的事件。例如pushButton最常见的信号是鼠标单击时发射一个clicked信号。

槽:对信号响应的函数。槽就是一个类成员函数可以是任何属性的(public、protected、private),可以带有参数、也可以被直接调用,槽函数与一般的函数的区别:槽函数可以与一个信号关联,当信号被发射时,关联的槽函数被自动执行。

当某个事件发生之后他就会发射一个信号,如果有对象对这个信号感兴趣,将信号和自己的一个函数(称之为槽(slot))绑定来处理这个函数,这个槽函数就会执行,也就是回调。所以槽的本质是一个类成员函数。

所有使用信号与槽的类中,必须有Q_OBJECT这个宏。

添加信号与槽

方法一

在UI界面编辑器中,我们手动从窗口添加一个信号与槽,假设我们想点击一下窗口上的按钮使窗口关闭程序退出。

我们可以先拉出一个Push Button组件,然后切换到第二个工具按钮

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Id0tSgtP-1687728177458)(C++.assets/image-20230613181326607.png)]

拖拽窗口拉出一根线后松开,会出现一个弹出框,左边是信号右边是槽

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RdiKeLfn-1687728177459)(C++.assets/image-20230613181516977.png)]

按需求选中对应的信号和槽后点击ok就可以了

这种方式的信号与槽是通过ui_mainwindow.h中的一行connect代码进行关联链接的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ylfyhuoY-1687728177460)(C++.assets/image-20230613182741254.png)]

方法二

还有一种比较快捷的添加方法,选中某个组件后右键点击转到槽,然后选择一个信号,然后就会在按钮的父窗口mainwindow中自动生成一个槽,也就是说这个信号的处理函数,由mainwindow中自定义函数处理。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ti7ElxnD-1687728177460)(C++.assets/image-20230613182946532.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oILqaOcO-1687728177461)(C++.assets/image-20230613183002379.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wWXv9Lbu-1687728177461)(C++.assets/image-20230613183022765.png)]

在.h文件中也会有相应的槽函数声明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h9WyVjP2-1687728177461)(C++.assets/image-20230613183055831.png)]

这种方式添加的信号槽并未直接用到connect函数关联绑定,而是在ui_mainwindow.h的setupUi中按name规则进行绑定的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1h2n2wC3-1687728177462)(C++.assets/image-20230613183251159.png)]

自定义信号与槽

在QMetaObject::connectSlotsByName(MainWindow);执行后,会自动匹配特定命名规则的槽函数,也就是说我们可以手动添加一个能被自动调用的槽函数。但这种方式并不是长久之计,如果我们手动指定信号与槽的绑定连接,需要用到函数QObject::connect。

//方式一:*(常用推荐)
QObject::connect(
	const QObject *sender,  //发出信号的对象
    const char *signal,     //发送对象发出的具体信号
    const QObject *receiver,//接收信号的对象
    const char *method,     //接收对象在接收信号之后所需要调用的函数
    Qt::ConnectionType type = Qt::AutoConnection  //连接类型
)
    
//方式一:*(常用推荐)
QMetaObject::connection QObject::connect(
	const QObject *sender,  
    PointerToMemberFunction signal,     
    const QObject *receiver,
    PointerToMemberFunction method,   
    Qt::ConnectionType type = Qt::AutoConnection  //连接类型
)   

方式一指定信号和槽分别用宏SIGNAL(a)和SLOT(a),这两个宏最终将信号槽转换为字符串。

connect中信号与槽需要指定函数名,参数列表形参类型但不包含其变量名,不需要返回值。

CheckBox

我们在设计界面向窗口内添加一个Check Box按钮和Label文本标记

然后手动的在主窗口头文件与源文件中声明和定义槽函数,并且在构造函数中对信号-槽进行绑定链接

槽函数声明

void slots_stateChange(int);  //返回类型为 void ,参数应当与信号保持一致

定义

void MainWindow::slots_stateChange(int a){}

连接

    //信号-槽 绑定连接
    connect(ui->checkBox/*信号的发送者(对象)*/,
            SIGNAL(stateChanged(int))/*信号*/,  //SIGNAL 宏 参数 为信号的函数名和参数列表,如果有形参名应当去掉
            this/*接收者(对象)*/,
            SLOT(slots_stateChange(int))/*接收的槽函数*/);

通过测试我们发现槽函数的形参a在勾选时为2,不勾选为0,那么就可以根据这个参数来改变文本标记

void MainWindow::slots_stateChange(int a){
    qDebug()<<"slots_stateChange :"<<a;
    if(a==0){  //不勾选
        ui->label->setText("不勾选");
    }else if(a==2){  //勾选
        ui->label->setText("勾选");
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9o9k3ZTM-1687728177462)(C++.assets/image-20230613191725120.png)]

我们发现参数状态是0,2缺少1。原来1代表的是半选状态。

所以我们可以在构造函数中去设置三态

ui->checkBox->setTristate(true);  //设置三态

这样就可以在槽函数中去对半选状态进行操作了

自定义QMessageBox

对于QMessageBox中提供的静态函数,只是支持已经定义好的一些按钮,却不支持自定义按钮。

所以我们尝试手动构建QMessageBox对话框,在MainWindiw构造函数中创建一个QMessageBox对象,并添加标题、文本和按钮。

    QMessageBox * pMsg = new QMessageBox;
    pMsg->setWindowTitle("title");
    pMsg->setText("我的文本");
    pMsg->addButton("是",QMessageBox::YesRole);
    pMsg->addButton("否",QMessageBox::NoRole);

然后我们可以在QMessageBox中找到对应的信号,所以此时信号发送者和信号还有接收者都有了,我们只需要再创建一个槽函数就可以了。

我们在头文件中去声明一下槽函数,参数与信号保持一致,然后在源文件中定义。这样我们就可以将信号与槽进行绑定链接了。

void slots_buttonClicked(QAbstractButton *button);
void MainWindow::slots_buttonClicked(QAbstractButton *button){
    
}

绑定链接

connect(pMsg,SIGNAL(buttonClicked(QAbstractButton *)),this,SLOT(slots_buttonClicked(QAbstractButton *)));

随后我们要对槽函数进行实现,参数中有一个button,我们可以利用这个参数来封装按钮,这个参数是之前写的按钮的返回值,所以我们在类成员属性中定义两个QPushButton*类型的变量用来接yes和no的返回值,然后由于我们创建QMessagebox时也是在构造函数中new的对象,所以就相当于是临时变量接了一个永久的对象,所以也将这个变量在类成员属性中去声明。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8VBbchEk-1687728177463)(C++.assets/image-20230614150142902.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-poCLM3jL-1687728177463)(C++.assets/image-20230614150154609.png)]

然后就可以根据这个返回值做对应操作了

void MainWindow::slots_buttonClicked(QAbstractButton *button){
    if(button == pYes){
        qDebug()<<"是";
    }else if(button == pNo){
        qDebug()<<"否";
    }
}

最后就是窗口显示,我们想让这个窗口与checkbox进行联系,所以就在checkbox的槽函数中如果勾选就显示窗口,不勾选就隐藏窗口就可以了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I3jhoZjC-1687728177463)(C++.assets/image-20230614150331911.png)]

测试一下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f1Q46bs8-1687728177464)(C++.assets/image-20230614150406156.png)]

点击是在控制台上也会输出“是”。

自定义信号

在mainwindow.ui设计界面添加一个按钮和一个单行文本输入框,然后直接右键按钮后选择转到槽 直接创建一个发射信号的槽函数。

然后在槽函数中获取编辑框中的文本,然后发射信号并且携带参数QString。

所以我们要自己定义一个信号,定义信号的关键字是signals,不能加访问修饰符,并且只声明不定义

signals:  //关键字修饰,不能加访问修饰符,只声明不定义
    void signals_sendQString(QString);

因为信号不是最终的执行者,就算定义了也用不了,所以干脆就不用定义

发射信号的槽函数,信号函数前面一般加一个emit,为的是告诉看代码的人这里不是正常的函数,而是一个信号,当然不写也没关系。

//发射信号
void MainWindow::on_pb_send_clicked(){
    QString str = ui->lineEdit->text();    //获取编辑框上的文本

    //发射信号,并且携带参数 QString
    emit signals_sendQString(str);
}

现在发送者有了,信号也有了,但是还没有接收者和接收的槽函数

我们决定发送给另一个窗口,现在只有一个mainwindow主窗口,所以要添加一个新的窗口

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D5rneNql-1687728177464)(C++.assets/image-20230614154514984.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2HBtbsOj-1687728177464)(C++.assets/image-20230614154531495.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bsZX02YU-1687728177465)(C++.assets/image-20230614154551593.png)]

之后完成就可以了,就会创建出一个新的头文件、源文件以及设计窗口

我们在这个窗口上添加一个lable,用来显示接收到的文本

现在接收者的类有了,但是对象还没有定义,我们在主函数中去定义一下这个对象。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-90sOPTfA-1687728177465)(C++.assets/image-20230614154813865.png)]

我们可以先不显示这个窗口,等到接收到信号之后在显示,那么接收的对象有了,就缺槽函数了

所以在这个窗口类中去声明定义槽函数,注意参数与信号保持一致就可以了,然后在定义时别忘了加类名作用域,否则就变成全局函数了。

public slots:
    void slots_recvQString(QString);
void Dialog::slots_recvQString(QString s){
}

最后就是连接了,我们要在主函数去连接信号与槽,因为信号和槽属于不同类,所以只能在主函数中去进行连接

QObject::connect(&w,SIGNAL(signals_sendQString(QString)),&dia,SLOT(slots_recvQString(QString)));

这里connect前要加QObject,之前不用加是因为mainwindow属于是它的子类,而main函数属于是外人,就不能直接使用。

然后在槽函数中实现显示接收到的文本信号并显示窗口就可以了

void Dialog::slots_recvQString(QString s){
    ui->label->setText(s);  //设置显示的文本
    this->show();
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ayMm9j5d-1687728177465)(C++.assets/image-20230614155524471.png)]

以上我们做的内容就是 通过自定义的信号槽以及手动的去绑定链接,实现了一个窗口到另一个窗口传递信息。

信号与槽多对多

一个信号连接多个槽

在窗口上添加一个水平滑块、一个时间编辑框和一个进度条共三个组件,想要通过水平滑块控制其他两个组件。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nxBXGyTP-1687728177466)(C++.assets/image-20230614231109395.png)]

现在我们是有了信号发出者和信号,也有信号接收者,只差槽函数

所以我们去声明定义分别与两个组件有关的槽函数

    void slots_timeChanged(int);
    void slots_progressChanged(int);

定义就先不写了

有了槽函数之后我们就可以对信号和槽进行绑定了,因为我们是一个信号连接多个槽,所以再绑定时只有槽函数位置不同

	connect(ui->horizontalSlider,SIGNAL(valueChanged(int)),this,SLOT(slots_timeChanged(int)));
    connect(ui->horizontalSlider,SIGNAL(valueChanged(int)),this,SLOT(slots_progressChanged(int)));

这样信号就与这两个槽函数绑定成功了,剩下的就是对槽函数进行实现了

因为我们水平滑块默认范围是0-99,我们想让他是0-100,所以我们手动设定一下水平滑块范围

   ui->horizontalSlider->setRange(0,100);

因为我们的时间编辑框想设为一天的时间,所以我们定义一个QTime,然后根据信号a的值给其赋值(一个单位代表多少秒)然后向这个组件传入这个时间就可以了。顺便我们也实值一下编辑框的显示格式

    ui->timeEdit->setDisplayFormat("hh-mm:ss");  //设置显示的格式
void MainWindow::slots_timeChanged(int a){
    qDebug()<<"a = "<<a;

    QTime time(0,0);  //定义一个初始时间
    time = time.addSecs(24*6*6*a);  //初始时间加上多少秒

    ui->timeEdit->setTime(time);  //时间组件上设置时间
}

进度条的槽函数时间就很简单了,只需要将整型信号当作进度条的值传入即可

void MainWindow::slots_progressChanged(int a){
    ui->progressBar->setValue(a);  //设置进度条的值
}

这样我们就实现了一个信号绑定多个槽了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-d7IoNbUd-1687728177466)(C++.assets/image-20230614234550612.png)]

多个信号连接一个槽

我们在主窗口添加两个push button按钮分别命名为门口开关和床头开关,想要让这两个开关的信号同时控制dialog窗口的显示与隐藏。

现在我们也是有信号发送者、信号和信号接收者,所以我们只需要去信号接收者类中写一个槽函数就可以进行连接了。

void slots_isShow();

有了槽函数之后我们开始连接,因为是两个窗口对象之间的连接,所以要在主函数中实现,不过在主函数中我们要调用主窗口的ui时我们发现ui被锁住了,原因是在类成员属性中我们将ui设为私有了,所以我们可以弄一个接口函数。

public:
    Ui::MainWindow * GetUI(){return ui;}

同时我们要在主函数中加上ui的头文件

#include "ui_mainwindow.h"

现在就可以实现链接了

    QObject::connect(w.GetUI()->pb_door,SIGNAL(clicked()),&dia,SLOT(slots_isShow()));
    QObject::connect(w.GetUI()->pb_bed,SIGNAL(clicked()),&dia,SLOT(slots_isShow()));

最后就是去实现槽函数的功能,我们想要的就是如果窗口显示那么按一下按钮就关闭,如果窗口关闭,那么按按钮就显示

void Dialog::slots_isShow(){
    if(this->isVisible()){  //是否可视
        this->hide();
    }else{
        this->show();
    }
}

现在就实现了只要任意一个信号发出(点击任何一个按钮),这个槽就会被调用(Dialog会显示或隐藏)。

一个信号连接一个信号连接一个槽

在主窗口添加一个SpinBox组件用来输入数字,然后在Dialog窗口上添加一个LCD Number组件,用来显示数字。我们想通过改变主窗口上的数字来同时对dialog上的数字进行更改。

正常思路就是向刚才我们写的主窗口的开关调用dialog窗口的显示一样。但是这里有一个限制,就是不能用ui的公共接口,所以我们需要自己声明一个信号,然后用已有信号连接到自己声明的信号,再用这个信号与槽进行连接。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W4N6LRDY-1687728177466)(C++.assets/image-20230615115942922.png)]

所以先自定义一个信号,参数与spinBox发送的信号保持一致

void signals_transportValue(int);  //信号,只声明

然后在mainwindow的构造函数中对两个信号进行连接

    //主窗口中的 spinBOx 信号 与 主窗口的信号进行连接
    connect(ui->spinBox,SIGNAL(valueChanged(int)),this,SIGNAL(signals_transportValue(int)));

这样我们只需要去主函数中将自定义信号和dialog的槽函数进行连接就可以了

先在dialog中声明一个槽函数

    void slots_setValue(int);

然后连接

    QObject::connect(&w,SIGNAL(signals_transportValue(int)),&dia,SLOT(slots_setValue(int)));

最后去定义一下槽函数就可以了

void Dialog::slots_setValue(int a){
    ui->lcdNumber->display(a);
}

这样我们就实现了信号->自定义信号->槽函数,其实不管多少个信号之间进行传递,最终都要有一个槽函数进行接收

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZXaNdc8W-1687728177467)(C++.assets/image-20230615120418834.png)]

断开连接

在主窗口上增加两个checkbox并命名为断开连接,作用是控制水平滑块和时间组件、进度条之间是否连接

我们可以直接通过转到槽来声明定义这两个状态改变的槽函数

这里断开连接的方式有两种

方法一

当参数为0就是不勾选,那么就重新连接,如果参数为2勾选就断开连接

我们可以在勾选时直接将连接函数改为disconnect,然后不勾选时还是connect

void MainWindow::on_cb_time_stateChanged(int arg1)
{
    if(arg1 == 0){  //不勾选 重新连接
        connect(ui->horizontalSlider,SIGNAL(valueChanged(int)),this,SLOT(slots_timeChanged(int)));
    }else if(arg1 == 2){  //勾选 断开连接
        disconnect(ui->horizontalSlider,SIGNAL(valueChanged(int)),this,SLOT(slots_timeChanged(int)));
    }
}

方法二

还有一种方法就是通过返回值来执行断开连接

我们在水平滑块和进度条连接函数前面加一个QMetaObject::Connection类型的返回值,这个返回值放到类成员属性中

    QMetaObject::Connection con;  //连接信息
con = connect(ui->horizontalSlider,SIGNAL(valueChanged(int)),this,SLOT(slots_progressChanged(int)));

然后在槽函数中如果勾选了就在disconnect()中填入返回值就可以了,如果没勾选就还是执行一遍连接函数,注意这里返回值不能省略

void MainWindow::on_cb_progress_stateChanged(int arg1)
{
    if(arg1 == 0){  //不勾选 重新连接
        con = connect(ui->horizontalSlider,SIGNAL(valueChanged(int)),this,SLOT(slots_progressChanged(int)));
    }else if(arg1 == 2){  //勾选 断开连接
        disconnect(con);  //直接传递,连接信息
    }
}

判断是否连接成功

返回值的作用还可以判断是否连接成功,如果返回为真就是成功,否则连接失败

    if(con){  //可用于判断是否连接成功
        qDebug()<<"连接成功";
    }else{
        qDebug()<<"连接失败";
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bgDSb1d6-1687728177467)(C++.assets/image-20230615122644504.png)]

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

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

相关文章

chatgpt赋能python:Python自动执行函数——提高生产力的利器

Python自动执行函数 —— 提高生产力的利器 Python作为一种高级编程语言&#xff0c;具有强大的自动化能力&#xff0c;可以轻松实现多种任务的自动执行&#xff0c;从而提高生产力和效率。这篇文章将介绍如何使用Python自动执行函数&#xff0c;以及它对于SEO的重要意义。 什…

Flutter Dart类

目录 类 构造函数 命名构造函数 重定向构造函数 常量构造函数 工厂构造函数 Getters 和 Setters 初始化列表 可覆写的操作符 类 创建一个dart文件&#xff0c;名称全小写&#xff0c;里面的类可以按照驼峰命名法。文件名和类名可以不保持统一&#xff0c;这个跟Java有明…

Scrapy: 一个强大的 Python 爬虫框架--介绍--下载--启动!!

目录 Scrapy 影响力 介绍 主要特点 架构 运行流程 基本使用 安装 创建 Scrapy 项目 创建爬虫 爬虫包含的内容 运行爬虫 Scrapy 影响力 作为目前爬虫主流框架之一&#xff0c;Scrapy的影响力和应用范围非常广泛&#xff1a; 根据GitHub上的数据&#xff0c;Scrapy是一…

ERR! code ERR_SOCKET_TIMEOUT

问题 安装npm包&#xff0c;终端报错ERR! code ERR_SOCKET_TIMEOUT ERR! code ERR_SOCKET_TIMEOUT详细问题 笔者运行以下命令重新安装依赖项&#xff1a; npm install控制台报错&#xff0c;具体报错信息如下 npm ERR! code ERR_SOCKET_TIMEOUT npm ERR! network Socket t…

【C++】【VLD】VLD检测内存泄漏

【C】【VLD】VLD检测内存泄漏 C/C 程序越复杂&#xff0c;内存的管理显得越重要&#xff0c;稍有不慎就会出现泄漏。如果内存泄漏不是很严重&#xff0c;在短时间内对程序不会有太大影响&#xff0c;这也使得内存泄漏问题有很强的隐蔽性&#xff0c;不易被发现。 然而不管内存…

计算机网络——传输层

序言 计算机网络中的传输层在当今的社会起到了什么作用&#xff1f; 计算机网络中的传输层在通信和数据传输方面起着至关重要的作用。传输层是计算机网络体系结构中的一层&#xff0c;它负责提供端到端的可靠数据传输和通信服务&#xff1b;有着以下几个方面作用&#xff1a;可…

3-css高级特效-2

01-空间转换 空间转换简介 空间&#xff1a;是从坐标轴角度定义的 X 、Y 和 Z 三条坐标轴构成了一个立体空间&#xff0c;Z 轴位置与视线方向相同。空间转换也叫 3D转换属性&#xff1a;transform 平移 transform: translate3d(x, y, z); transform: translateX(); transfor…

chatgpt赋能python:Python聊天机器人程序:把智能带入聊天

Python聊天机器人程序&#xff1a;把智能带入聊天 在数字化时代&#xff0c;机器人指引和客户服务变得越来越流行。为了快速而有效地满足这种需求&#xff0c;聊天机器人被广泛研究与开发。Python是在这方面一个非常受欢迎的编程语言&#xff0c;能够快速地构建聊天机器人。在…

【C++】win 10 / win 11:Visual Studio 2022 社区版免费下载与安装

目录 一、Visual Studio 2022 下载 二、Visual Studio 2022 安装 三、Visual Studio 2022 快捷方式创建 四、Visual Studio 2022 使用 一、Visual Studio 2022 下载 Visual Studio 2022 官方下载https://visualstudio.microsoft.com/zh-hans/downloads/首先登陆 Visual Stu…

基于Java医院在线挂号预约系统设计实现(源码+lw+部署文档+讲解等)

博主介绍&#xff1a; ✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精…

Jmeter简单实现登录测试

目录 前言&#xff1a; 1、添加线程组--在测试计划上右击-添加-Threads-线程组 2、添加http请求默认值--在线程组上右击-添加-配置元器件-http请求默认值 3、添加sampler-http请求-登录界面 4、添加sampler-http请求-登录-携带用户名和密码 5、创建存放用户名和密码的文件…

数通王国历险记之TCP协议下的三大协议的验证实验

系列文章目录 数通王国历险记&#xff08;1&#xff09; 前言 一&#xff0c;我们要先知道PDU是什么&#xff1f; 二、TCP协议下的三大协议的验证实验 1.FTP的验证实验 1&#xff0c;拓扑图 2.将lsw4配置一下 3&#xff0c;FTP服务器端开启FTP服务&#xff1a; 4&#x…

SpringBoot 如何使用 TestEntityManager 进行 JPA 集成测试

SpringBoot 如何使用 TestEntityManager 进行 JPA 集成测试 简介 在开发过程中&#xff0c;JPA 是常用的持久化框架之一&#xff0c;它可以帮助我们将对象映射到数据库中&#xff0c;并提供了一系列操作数据库的 API。在进行 JPA 的开发和测试时&#xff0c;我们通常会使用一…

Mybatis实现分页功能

1、关于逻辑分类和物理分页 分页可分为逻辑分页和物理分页 逻辑分页是一次性把全部数据查询加载进内存 &#xff0c;然后再进行分页。这样优点是减少IO次数&#xff0c;适合频繁访问、数据量少的情况。缺点是不适合大数据量&#xff0c;容易造成内存溢出。物理分页是利用limi…

Android JVM 原理简析

当我们在开发 Android 应用程序时&#xff0c;我们实际上是在使用 Java 编程语言编写代码&#xff0c;并将其编译为在 Android 上运行的字节码。这些字节码最终在 Android 设备上的 Java 虚拟机&#xff08;JVM&#xff09;中执行。 Android JVM的意义 学习 Android JVM&#…

Java基础知识面试题

Java概述 何为编程 编程就是使用某种程序设计语言编写程序代码让计算机解决某个问题 为了使计算机能够理解人的意图&#xff0c;人类就必须要将需解决的问题的思路、方法、和手段通过计算机能够理解的形式告诉计算机&#xff0c;使得计算机能够根据人的指令一步一步去工作&a…

Spring相关API

⭐作者介绍&#xff1a;大二本科网络工程专业在读&#xff0c;持续学习Java&#xff0c;努力输出优质文章 ⭐作者主页&#xff1a;逐梦苍穹 ⭐所属专栏&#xff1a;JavaEE、Spring SpringAPI 1、继承体系2、 getBean() 1、继承体系 上述继承体系中的主要类和接口包括&#xff1…

WebRTC-STUN协议详解

1、STUN协议概述 STUN&#xff08;Session Traversal Utilities for NAT&#xff09;NAT会话穿透工具&#xff0c;STUN是一个Client/Server协议&#xff0c;支持请求/响应类型、指示类型两种类型。STUN作为ICE&#xff08;Interactive Connectivity Establishment&#xff0c;…

【需求实现】输入多少就输出多少的拟合任务如何实现(一):数据集分割

神经网络中输入多少数据就输出多少数据的情况如何实现 导读数据集长什么样&#xff1f;怎么分割数据集&#xff1f;时间窗口分析模板我知道你很急&#xff0c;但你先别急 换个思路 导读 在实习的过程中遇到了这样一种需求&#xff1a;给定一条序列&#xff0c;并另外给定一条期…

使用ffmpeg将rtsp流转流实现h5端播放

主要实现rtsp转tcp协议视频流播放 ffmpeg下载安装&#xff08;公认业界视频处理大佬&#xff09; a、官网地址&#xff1a;www.ffmpeg.org/ b、gitHub&#xff1a;github.com/FFmpeg/FFmp… c、推荐下载地址&#xff1a;ffmpeg.zeranoe.com/builds/ (选择如下图) 2.配置ffmpeg…