【QT八股文】系列之篇章2 | QT的信号与槽机制及通讯流程

【QT八股文】系列之篇章2 | QT的信号与槽机制及通讯流程

  • 前言
  • 2. 信号与槽
    • 信号与槽机制介绍/本质/原理,什么是Qt信号与槽机制?如何在Qt中使用?
    • 信号与槽机制原理,解析流程
    • Qt信号槽的调用流程
    • 信号与槽机制的优缺点
    • 信号与槽机制需要注意的问题
    • 信号的注意点
    • 信号与槽与回调函数区别
    • Qt信号与槽的多种用法
    • PYQT5 connect 函数
    • Qt connect 函数的连接方式
    • PYQT5信号槽的链接方式
    • 信号槽同步与异步/多线程下,信号槽分别在什么线程中执行,如何控制——`Qt connect 函数的连接方式`来控制
  • 3. 通讯流程
    • QT的TCP通讯流程
    • QT的UDP通讯流程
  • 下一章笔记
  • 说明

前言

第一篇章主要是基础定义及QT中重要的事件机制
笔记链接:【QT八股文】系列之篇章1 | QT的基础知识及事件/机制

这里我们在了解了QT的大概后,我们将来了解QT中的核心机制:信号与槽
因为介绍到信号与槽,所以笔者我会讲通讯流程提前在前面来介绍

原创文章,未经同意请勿转载

2. 信号与槽

信号与槽机制介绍/本质/原理,什么是Qt信号与槽机制?如何在Qt中使用?

在这里插入图片描述

  • 定义
    Qt信号与槽机制是一种基于事件机制的编程模型,用于对象之间的通信。信号是由发送方对象发射的事件,而槽是接收方对象用于处理这些事件的函数。在Qt中,我们可以使用QObject类中的信号和槽机制来实现对象间的通信。通过定义信号和槽函数,在信号发射时,会自动调用对应的槽函数进行处理。

  • 使用
    PyQt的内置信号是自动定义的,使用PyQt5.QtCore.pyqtSignal函数可以为QObject对象创建一个信号,使用pyqtSignal函数可以把信号定义为类的属性。使用connect函数可以将信号绑定到槽函数上,使用disconnect函数可以解除信号与槽函数的绑定,使用emit函数可以发射信号。

  • 本质(就是回调函数)
    在事件的处理方面,信号槽相比回调函数,具有类型安全、松耦合、任意参数的优势,但执行效率会有一点损失。信号相当于传递参数(指实参,用于传递值/动作变化),槽函数像用于传递函数体(形参/函数体,用于接收值/根据动作变化来做出对应操作。)

  • 原理

    1. Qt 中的信号与槽机制是一种事件处理机制,它允许程序在接收到特定事件时执行特定的操作。在 Qt 中,信号与槽机制被广泛应用于组件之间的通信和事件处理。
    2. 具体来说,Qt 中的信号与槽机制是基于 QObject 类的。任何一个 QObject 对象都可以作为一个信号源,它可以通过 emit() 方法发出信号。同时,任何一个 QObject 对象都可以作为一个槽,它可以接受并处理来自信号源的信号。当一个信号源发出信号时,它会连接到相应的槽。这些槽可以是与信号源同一个对象,也可以是其他 QObject 对象。当信号源接收到信号时,它会将信号传递给所有已经连接到该槽的对象。这些对象会在接收到信号时执行相应的操作。

信号与槽机制原理,解析流程

在这里插入图片描述

  • 原理

    1. Qt 中的信号与槽机制是一种事件处理机制,它允许程序在接收到特定事件时执行特定的操作。在 Qt 中,信号与槽机制被广泛应用于组件之间的通信和事件处理。
    2. 具体来说,Qt 中的信号与槽机制是基于 QObject 类的。任何一个 QObject 对象都可以作为一个信号源,它可以通过 emit() 方法发出信号。同时,任何一个 QObject 对象都可以作为一个槽,它可以接受并处理来自信号源的信号。当一个信号源发出信号时,它会连接到相应的槽。这些槽可以是与信号源同一个对象,也可以是其他 QObject 对象。当信号源接收到信号时,它会将信号传递给所有已经连接到该槽的对象。这些对象会在接收到信号时执行相应的操作。
  • 解析流程

    1. moc查找头文件中的signals,slots,标记出信号和槽。
    2. 将信号槽信息存储到类静态变量staticMetaObject中,并且按声明顺序进行存放,建立索引。
    3. 当发现有connect连接时,将信号槽的索引信息放到一个map中,彼此配对。
    4. 当调用emit时,调用信号函数,并且传递发送信号的对象指针,元对象指针,信号索引,参数列表到active函数
    5. 通过active函数找到在map中找到所有与信号对应的槽索引
    6. 根据槽索引找到槽函数,执行槽函数。

Qt信号槽的调用流程

注意:信号槽的实现:元对象编译器MOC,MOC的本质就是反射器

  • MOC(元对象编译器)查找头文件中的signal与slots,标记出信号槽。将信号槽信息储存到类静态变量staticMetaObject中,并按照声明的顺序进行存放,建立索引。
  • connect链接,将信号槽的索引信息放到一个双向链表中,彼此配对。
  • emit被调用,调用信号函数,且传递发送信号的对象指针,元对象指针,信号索引,参数列表到active函数。
  • active函数在双向链表中找到所有与信号对应的槽索引,根据槽索引找到槽函数,执行槽函数。

信号与槽机制的优缺点

  • 优点
    • 类型安全。需要关联的信号槽的签名必须是等同的。即信号的参数类型和参数个数同接受该信号的槽的参数类型和参数个数相同。若信号和槽签名不一致,编译器会报错。信号的参数可以多于槽,槽参数数量不能大于于信号

      💡 槽函数的参数是否可以比信号的参数多?
      也可以。唯一的情况就是槽函数参数带有默认参数,除去默认参数外,槽函数的参数必须小于等于信号的参数。

    • 松散耦合。QT的信号槽的建立和解除绑定十分自由。信号和槽机制减弱了Qt对象的耦合度。激发信号的Qt对象无需知道是那个对象的那个信号槽接收它发出的信号,它只需在适当的时间发送适当的信号即可,而不需要关心是否被接受和那个对象接受了。Qt就保证了适当的槽得到了调用,即使关联的对象在运行时被删除。程序也不会奔溃。

      💡 信号重载了,如何确定连接哪个信号?
      采用函数指针确定连接哪个信号。

    • 灵活性。一个信号可以关联多个槽,或多个信号关联同一个槽。

  • 不足
    • 速度较慢。与回调函数相比,信号和槽机制运行速度比直接调用非虚函数慢10倍。信号槽同真正的回调函数比起来时间的耗损还是很大的,所以在嵌入式实时系统中应当慎用。
      • 原因:
        • ①需要定位接收信号的对象。
        • ②安全地遍历所有关联槽。
        • ③编组、解组传递参数。
        • ④多线程的时候,信号需要排队等待。(然而,与创建对象的new操作及删除对象的delete操作相比,信号和槽的运行代价只是他们很少的一部分。信号和槽机制导致的这点性能损耗,对实时应用程序是可以忽略的。
    • 不能出现宏定义。信号槽的参数限定很多例如不能携带模板类参数,不能出现宏定义等等。

信号与槽机制需要注意的问题

信号与槽机制是比较灵活的,但有些局限性我们必须了解,这样在实际的使用过程中才能够做到有的放矢,避免产生一些错误。下面就介绍一下这方面的情况。

  • 信号与槽的效率是非常高的,但是同真正的回调函数比较起来,由于增加了灵活 性,因此在速度上还是有所损失,当然这种损失相对来说是比较小的,通过在一台 i586- 133 的机器上测试是 10 微秒(运行 Linux),可见这种机制所提供的简洁性、灵活性还是 值得的。但如果我们要追求高效率的话,比如在实时系统中就要尽可能的少用这种机制。
  • 信号与槽机制与普通函数的调用一样,如果使用不当的话,在程序执行时也有可能 产生死循环。因此,在定义槽函数时一定要注意避免间接形成无限循环,即在槽中再次发射 所接收到的同样信号。
  • 如果一个信号与多个槽相关联的话,那么,当这个信号被发射时,与之相关的槽被 激活的顺序将是随机的,并且我们不能指定该顺序。
  • 宏定义不能用在 signal 和 slot 的参数中。
  • 构造函数不能用在 signals 或者 slots 声明区域内。
  • 函数指针不能作为信号或槽的参数。
  • 信号与槽不能有缺省参数。
  • 信号与槽也不能携带模板类参数。

信号的注意点

  • 所有的信号声明都是公有的,所以Qt规定不能在signals前面加public,private, protected。
  • 所有的信号都没有返回值,所以返回值都用void。
  • 所有的信号都不需要定义。
  • 必须直接或间接继承自QOBject类,并且开头私有声明包含Q_OBJECT。
  • 在同一个线程中,当一个信号被emit发出时,会立即执行其槽函数,等槽函数执行完毕后,才会执行emit后面的代码,如果一个信号链接了多个槽,那么会等所有的槽函数执行完毕后才执行后面的代码,槽函数的执行顺序是按照它们链接时的顺序执行的。不同线程中(即跨线程时),槽函数的执行顺序是随机的。
  • 在链接信号和槽时,可以设置链接方式为:在发出信号后,不需要等待槽函数执行完,而是直接执行后面的代码,是通过connect的第5个参数。
  • 信号与槽机制要求信号和槽的参数一致,所谓一致,是参数类型一致。如果不一致,允许的情况是,信号的参数可以比槽函数的参数多,即便如此,槽函数存在的那些参数的顺序也必须和信号的前面几个一致起来。这是因为,你可以在槽函数中选择忽略信号传来的数据(也就是槽函数的参数比信号的少),但是不能说信号根本没有这个数据,你就要在槽函数中使用(就是槽函数的参数比信号的多,这是不允许的)。

信号与槽与回调函数区别

  1. 链接的不同

    • 回调函数使用函数指针来实现的,如果多个类都关注一个类的动态变化,这样就会需要写出一个比较长的列表来管理这些类之间的关系。稍微在编码方面不那么灵活,稍显冗余。
    • QT使用信号与槽来解决这个连接问题,这种方式比较清晰简单一些,一个类只需要清楚自己有几个槽函数有几个信号,然后将信号与槽进行连接,QT会自己处理函数的调用关系。这样在软件设计角度更加的清晰,灵活,不容易出错。
  2. 执行顺序/时间的不同

    • Qt 信号与槽机制中的槽函数在接收到信号时会自动执行,而回调函数通常是在调用时立即执行。Qt 信号与槽机制可以在信号触发时立即执行槽函数,也可以延迟执行槽函数,而回调函数通常是立即执行的。
    • 信号与槽机制中的信号与槽之间的执行顺序是不确定的,可以是任意顺序,也可以是逆序;而回调函数机制中的回调函数之间的执行顺序通常是确定的,按照函数声明的顺序执行。
  3. 对象绑定

    信号与槽机制可以实现对象之间的动态绑定,可以在运行时动态地绑定信号与槽;而回调函数机制通常只能在程序启动时进行绑定。

  4. 主要用途不同

    信号和槽机制是用于在程序运行时传递数据和事件的机制,而回调函数则通常被用于函数或方法的调用。因此,信号和槽机制可以用于模块之间的通信和交互,而回调函数则通常用于函数或方法的调用。

Qt信号与槽的多种用法

  • 一个信号可以和多个槽相连
    这时槽的执行顺序和在不在同一个线程上有关,同一线程,槽的执行顺序和声明顺序有关,跨线程时,执行顺序是不确定的。
  • 多个信号可以连接到一个槽
    只要任意一个信号发出,这个槽就会被调用。
  • 一个信号可以连接到另外的一个信号
    当第一个信号发出时,第二个信号被发出。除此之外,这种信号-信号的形式和信号-槽的形式没有什么区别。
  • 槽可以被取消链接
    这种情况并不经常出现,因为当一个对象delete之后,Qt自动取消所有连接到这个对象上面的槽。想主动取消连接就用disconnect()函数中添加任何实现。
  • 可以使用Lambda 表达式
    在使用 Qt 5 的时候,能够支持 Qt 5 的编译器都是支持 Lambda 表达式的。

PYQT5 connect 函数

注:在Qt中第五个参数用于指定信号与槽的匹配规则。而PYQT5是第四个参数
在 PyQt5 中,connect 函数【connect: PyQt5.QtWidgets.QSignalMapper()】是一个用于连接信号与槽的函数。它通常被用于将对象的信号与槽函数进行连接。

列子:mapper = Qt.QSignalMapper() mapper.setMapping(button, button.clicked.connect(mapper.setCurrentIndex))

第一个参数是一个可选的参数,用于指定要连接的信号源。如果该参数为 None,则表示连接的是系统提供的信号。如果该参数不为 None,则表示要连接自定义信号。

第二个参数是一个可选的参数,用于指定要连接的槽函数。如果该参数为 None,则表示连接的是默认槽函数。如果该参数不为 None,则表示要连接指定的槽函数。

第三个参数是一个字符串,用于指定信号与槽之间的映射关系。该字符串通常由信号名称和槽函数名称组成。例如,“clicked” 表示将按钮的点击信号与按钮的 clicked 槽函数进行连接。

第四个参数是一个 PyQt5 中的 QSignalMapper 对象,用于指定信号与槽的匹配规则。该对象应该实现 QSignalMapper 类中的方法,例如 setMapping() 和 currentIndex() 等。

第五个参数是一个可选的参数,用于指定信号中断连接的函数。如果连接的信号源对象被删除或重新分配,则连接将被中断。默认情况下,连接不会自动中断。

Qt connect 函数的连接方式

  1. 自动连接Qt::AutoConnection
    默认值,使用这个值则连接类型会在信号发送时决定。如果接收者和发送者在同一个线程,则自动使用
    多线程时为队列连接函数,单线程时为直接连接函数。

  2. 直接连接Qt::DirectConnection
    == 如果接收者和发送者不在一个线程,则自动使用Qt::QueuedConnection类型。==
    Qt::DirectConnection:槽函数会在信号发送的时候直接被调用,槽函数和信号发送者在同一线程。效果看上去就像是直接在信号发送位置调用了槽函数,效果上看起来像函数调用,同步执行。
    emit语句后面的代码将在与信号关联的所有槽函数执行完毕后才被执行。
    信号/槽在信号发出者所在的线程中执行

  3. 队列连接Qt::QueuedConnection
    信号发出后,信号会暂时被放到一个消息队列中,需等到接收对象所属线程的事件循环取得控制权时才取得该信号,然后执行和信号关联的槽函数,这种方式既可以在同一线程内传递消息也可以跨线程操作。
    emit语句后的代码将在发出信号后立即被执行,无需等待槽函数执行完毕
    信号在信号发出者所在的线程中执行,槽函数在信号接收者所在的线程中执行

  4. Qt::BlockingQueuedConnection
    槽函数的调用时机与Qt::QueuedConnection一致,不过发送完信号后发送者所在线程会阻塞,直到槽函数运行完。而且接收者和发送者绝对不能在一个线程,否则程序会死锁。在多线程间需要同步的场合可能需要这个。

  5. Qt::UniqueConnection:这个flag可以通过按位或(|)与以上四个结合在一起使用。当这个flag设置时,当某个信号和槽已经连接时,再进行重复的连接就会失败。也就是为了避免重复连接。

PYQT5信号槽的链接方式

在 PyQt5 中,信号与槽的连接方式有两种:1. 使用 connect() 函数;2. 装饰器@pyqtSlot() 。

@pyqtSlot()优点是方式书写比较简洁。缺点是但函数名称不能自由定义,在想自定义参数时没有详细说明。

connect()方式优点是理解和学习起来比较简单,而且函数名称可以自由定义。缺点是但如果信号比较多时,书写就比较混乱。

使用信号处理器的优点是可以在信号发生时执行复杂的操作,而缺点是连接信号处理器需要花费更多的内存和时间,并且连接信号处理器需要手动管理连接关系。因此,使用信号处理器仅适用于需要执行复杂操作的情况。

  1. 装饰器方法:@pyqtSlot()装饰器

    @pyqtSlot():修饰关键词,表明下面是完整的信号槽函数

    # 需要引入 pyqtSlot 库函数
    from PyQt5.QtCore import pyqtSlot
    
    @pyqtSlot() #装饰器,此函数没有connect直接通过装饰器初始化连接槽函数
    def on_pushButton_clicked(self)
    	print("我点击了")
    

    在@pyqtSlot()方式里,函数名称有特殊要求,如下:

    def  on_(控件对象名)_信号名(self,内置参数)

    @pyqtSlot()控制控件的多信号

    @pyqtSlot()
    def on_lineEdit_returnPressed(self):
    	print('触发了信号 returnPressed')
    
    def on_lineEdit_textChanged(self):
    	print('触发了信号 textChanged')
    

    注意:一个控件同时要写多个信号与槽函数时,只需要写一遍@pyqtSlot()关键词,中间可以有其他函数隔开。一定是一个类里面的,一个控件只写一遍@pyqtSlot(),不是所有控件信号只写一次@pyqtSlot(),有多少控件的信号还是要写。

  2. connect连接法

    使用 connect() 函数将信号与槽函数连接起来。connect() 函数接受两个参数:要连接的信号和要连接的槽函数。连接成功后,当信号发生时,槽函数将被调用。

    # 在初始化函数中信号连接槽函数
    self.pushButton.clicked.connect(self.test)
    # 槽函数
    def test(self):
    	print("点击了一下")
    

    规则:

    • 语法规则:self.控件对象名称.信号名称.connect(self.槽函数名称)
    • 有参数时,槽函数名称部分写成lambda 参数名: 函数名(参数名)
    • 没有参数时,槽函数不用写括号()

信号槽同步与异步/多线程下,信号槽分别在什么线程中执行,如何控制——Qt connect 函数的连接方式来控制

可以通过QT的connect函数的第五个参数(PYQT5中是第四个参数)来控制, 信号槽执行时所在的线程。

通常使用的connect,实际上最后一个参数使用的是Qt::AutoConnection类型:Qt支持6种连接方式,其中3中最主要:

  1. Qt::AutoConnection(自动方式)

    信号槽在信号发出者所在的线程中执行

    Qt的默认连接方式,如果信号的发出和接收这个信号的对象同属一个线程,那个工作方式与直连方式相同(会自动使用Qt::DirectConnection类型);否则工作方式与排队方式相同(会自动使用Qt::QueuedConnection类型)。

    即多线程时为队列连接函数,单线程时为直接连接函数。

  2. Qt::DirectConnection(直连方式)(信号与槽函数关系类似于函数调用,同步执行)

    当信号发出后,相应的槽函数将立即被调用。emit语句后的代码将在所有槽函数执行完毕后被执行。

  3. Qt::QueuedConnection(排队方式)(此时信号被塞到信号队列里了,信号与槽函数关系类似于消息通信,异步执行)

    信号在信号发出者所在的线程中执行,槽函数在信号接收者所在的线程中执行

    当信号发出后,排队到信号队列中,需等到接收对象所属线程的事件循环取得控制权时才取得该信号,调用相应的槽函数。emit语句后的代码将在发出信号后立即被执行,无需等待槽函数执行完毕。

  4. Qt::BlockingQueuedConnection(信号和槽必须在不同的线程中,否则就产生死锁)

    这个是完全同步队列只有槽线程执行完成才会返回,否则发送线程也会一直等待,相当于是不同的线程可以同步起来执行

    与Qt::QueuedConnection相同,除了信号线程阻塞直到槽返回。如果接收方处于发送信号的线程中,则不能使用此连接,否则应用程序将死锁。

  5. Qt::UniqueConnection

    与默认工作方式相同,只是不能重复连接相同的信号和槽,因为如果重复连接就会导致一个信号发出,对应槽函数就会执行多次。

    这个flag可以通过按位或(|)与以上四个结合在一起使用。当这个flag设置时,当某个信号和槽已经连接时,再进行重复的连接就会失败。也就是为了避免重复连接。

  6. Qt::AutoCompatConnection

    是为了连接Qt4与Qt3的信号槽机制兼容方式,工作方式与Qt::AutoConnection一样。

3. 通讯流程

QT的TCP通讯流程

在这里插入图片描述
QT如果要进行网络编程首先需要在.pro中添加如下代码:QT += network

  • 服务端:(QTcpServer)
    ① 创建QTcpServer对象
    ② 监听list需要的参数是地址和端口号
    ③ 当有新的客户端连接成功回发送newConnect信号
    ④ 在newConnection信号槽函数中,调用nextPendingConnection函数获取新连接QTcpSocket对象
    ⑤ 连接QTcpSocket对象的readRead信号
    ⑥ 在readRead信号的槽函数使用read接收数据
    ⑦ 调用write成员函数发送数据

  • 服务器端

    1. 创建用于监听的套接字

    2. 给套接字设置监听

    3. 如果有连接到来, 监听的套接字会发出信号newConnected

    4. 接收连接, 通过nextPendingConnection()函数, 返回一个QTcpSocket类型的套接字对象(用于通信)

    5. 使用用于通信的套接字对象通信 1>. 发送数据: write 2>. 接收数据: readAll/read

      • 代码

        Widget::Widget(QWidget *parent) :
            QWidget(parent),
            ui(new Ui::Widget)
        {
            ui->setupUi(this);
            tcpServer = new QTcpServer;
            tcpServer->listen(QHostAddress("192.168.0.111"),1234);
            connect(tcpServer,SIGNAL(newConnection()),this,SLOT(new_connect()));
        }
         
        Widget::~Widget()
        {
            delete ui;
        }
         
        void Widget::new_connect()
        {
            qDebug("--new connect--");
            QTcpSocket* tcpSocket = tcpServer->nextPendingConnection();
            connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(read_data()));
            socketArr.push_back(tcpSocket);
         
        }
         
        void Widget::read_data()
        {
            for(int i=0; i<socketArr.size(); i++)
            {
                if(socketArr[i]->bytesAvailable())
                {
                    char buf[256] = {};
                    socketArr[i]->read(buf,sizeof(buf));
                    qDebug("---read:%s---",buf);
                }
            }
        }
        
  • 客户端:(QTcpSocket)
    ① 创建QTcpSocket对象
    ② 当对象与Server连接成功时会发送connected 信号
    ③ 调用成员函数connectToHost连接服务器,需要的参数是地址和端口号
    ④ connected信号的槽函数开启发送数据
    ⑤ 使用write发送数据,read接收数据

  • 客户端:

    1. 创建用于通信的套接字
    2. 连接服务器: connectToHost
    3. 连接成功与服务器通信
      1 >. 发送数据: write 2>. 接收数据: readAll/read
    • 代码

      Widget::Widget(QWidget *parent) :
          QWidget(parent),
          ui(new Ui::Widget)
      {
          ui->setupUi(this);
          tcpSocket = new QTcpSocket;
          connect(tcpSocket,SIGNAL(connected()),this,SLOT(connect_success()));
          tcpSocket->connectToHost("172.20.10.3",1234);
      }
       
      Widget::~Widget()
      {
          delete ui;
      }
       
      void Widget::on_send_clicked()
      {
          std::string msg = ui->msg->text().toStdString();
          int ret = tcpSocket->write(msg.c_str(),msg.size()+1);
          qDebug("--send:%d--",ret);
      }
       
      void Widget::connect_success()
      {
          ui->send->setEnabled(true);
      }
      

QT的UDP通讯流程

UDP(User Datagram Protocol即用户数据报协议)是一个轻量级的,不可靠的,面向数据报的无连接协议。在网络质量令人十分不满意的环境下,UDP协议数据包丢失严重。由于UDP的特性:它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用UDP较多,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。所以QQ这种对保密要求并不太高的聊天程序就是使用的UDP协议。

在Qt中提供了QUdpSocket 类来进行UDP数据报(datagrams)的发送和接收。Socket简单地说,就是一个IP地址加一个port端口 。

QT下UDP通信服务器端和客户端的关系是对等的, 做的处理也是一样的:

  1. 创建套接字对象 2. 如果需要接收数据, 必须绑定端口 3. 发送数据: writeDatagram 4. 接收数据: readDatagram

流程:①创建QUdpSocket套接字对象 ②如果需要接收数据,必须绑定端口 ③发送数据用writeDatagram,接收数据用 readDatagram 。

下一章笔记

下篇笔记链接:【QT的多线程以及QThread与QObject】
下篇笔记主要内容:QT的多线程以及QThread与QObject

说明

码字不易,可能当中存在某些字体错误(笔者我没有发现),如果有错误,欢迎大家指正。🤗
另外因为笔记是之前做的,这里我只把我之前做的搬移和重新排版过来,如果有知识上的错误也欢迎大家指正。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

明天(周六)下午!武汉Linux爱好者线下沙龙,我们在华中科技大学等你!

2024 年 5月 25 日&#xff08;周六&#xff09;下午&#xff0c;我们将在「武汉市洪山区」 珞喻路 1037 号华中科技大学南五楼 613 室举办武汉 Linux 爱好者线下沙龙&#xff08;WHLUG&#xff09;&#xff0c;欢迎广大 Linux 爱好者来到现场&#xff0c;与我们一同交流技术&a…

【vue echart】完成一个简单echart图表+自适应

实现效果&#xff1a; html&#xff1a; <divref"echartOne"id"echartOne"style"width: 100%; height: 100%" ></div> js: getEchartOne() {let chart this.$echarts.init(this.$refs.echartOne);chart.setOption({title: {text:…

科技产业园3D探秘:未来科技之城的奇幻之旅

在数字时代的浪潮中&#xff0c;科技产业园区成为了推动城市经济发展、科技创新的重要引擎。 当我们打开科技产业园的3D可视化模型&#xff0c;仿佛穿越时空&#xff0c;来到了一个充满奇幻色彩的科技世界。在这里&#xff0c;高楼大厦鳞次栉比&#xff0c;绿色植被点缀其间&am…

Python协程的作用

过分揣测别人的想法&#xff0c;就会失去自己的立场。大家好&#xff0c;当代软件开发领域中&#xff0c;异步编程已成为一种不可或缺的技术&#xff0c;用于处理大规模数据处理、高并发网络请求、实时通信等应用场景。而Python协程&#xff08;Coroutine&#xff09;作为一种高…

数组-区间合并

一、题目描述 二、题目思路 这里提供满足基本要求的解题思路&#xff1a; 1.先对列表内按照start大小升序排序&#xff0c;这里创建Comparator接口的实现类&#xff0c;重写compare方法。 2.遍历intervals&#xff0c;设置laststart、lastend两个变量与当前区间相比较&#…

JavaEE技术之分布式事务(理论、解决方案、Seata解决分布式事务问题、Seata之原理简介、断点查看数据库表数据变化)

文章目录 JavaEE技术之分布式事务准备:1. 本地事务回顾1.1 什么是事务1.2 事务的作用1.3 事务ACID四大特性1.4 事务的并发问题1.5 MySQL事务隔离级别1.6 事务相关命令(了解)1.7 事务传播行为&#xff08;propagation behavior&#xff09;1.8 伪代码练习1.9 回滚策略1.10 超时事…

arcgisPro精确移动要素某一点至指定点位

1、打开要素&#xff0c;如下&#xff1a; 2、选择移动工具&#xff0c;如下&#xff1a; 3、选择需要移动的要素&#xff0c;如下&#xff1a; 4、按住Ctrl键&#xff0c;移动锚点的位置至三角形顶点位置&#xff0c;如下&#xff1a; 5、拖动锚点至上面多边形的左上角点&…

CS西电高悦计网课设——校园网设计

校园网设计 一&#xff0c;需求分析 所有主机可以访问外网 主机可以通过域名访问Web服务器 为网络配置静态或者动态路由 图书馆主机通过DHCP自动获取IP参数 为办公楼划分VLAN 为所有设备分配合适的IP地址和子网掩码&#xff0c;IP地址的第二个字节使用学号的后两位。 二…

K8s资源限制和三种探针

一 默写总结 1 pod 的组成 ① Pod 中有几种容器 init 初始化 &#xff0c;阻塞主容器运行&#xff0c;初始化后方可运行主容器 pause 基础容器&#xff1a; 提供network 的 namespace 和 共享存储 业务容器&#xff1a; 跑Pod 主应用 &#xff08;POD中跑什么&#xff1a;微…

MySQL-性能分析

1、数据库服务器的优化步骤 2、查看系统性能参数 可以使用show status语句查询一些MySQL数据库服务器的性能参数 执行频率语法格式&#xff1a;show [ global | session ] status like 参数 &#xff1b;常用性能参数如下所示 参数名说明connection连接MySQL服务器的次数upti…

某大型制造集团企业信息化建设总体规划设计方案(67页PPT)

方案介绍&#xff1a; 随着信息技术的飞速发展&#xff0c;企业信息化建设已成为提高管理效率、增强企业竞争力的重要手段。某大型制造集团为应对市场变化、提升管理水平、优化资源配置&#xff0c;决定进行全面深入的信息化建设。本方案旨在构建一个集生产、管理、销售、物流…

Linux程序开发(十):文件分类器趣味设计

Tips&#xff1a;"分享是快乐的源泉&#x1f4a7;&#xff0c;在我的博客里&#xff0c;不仅有知识的海洋&#x1f30a;&#xff0c;还有满满的正能量加持&#x1f4aa;&#xff0c;快来和我一起分享这份快乐吧&#x1f60a;&#xff01; 喜欢我的博客的话&#xff0c;记得…

Win10蓝牙鼠标不能移动问题解决

问题描述&#xff1a;鼠标是没损坏的&#xff0c;使用过程中&#xff0c;光标突然就不能移动了&#xff0c;但右键和滚轮还是有反应。 解决&#xff1a; 1&#xff0c;删除蓝牙设置中的如下配置&#xff08;我只使用了无线鼠标&#xff0c;没有无线键盘&#xff09; 2&#x…

智慧校园为高校带来哪些价值

在21世纪的教育图景中&#xff0c;"智慧"不再仅仅是一个科技名词&#xff0c;它已成为衡量教育现代化水平的重要标志。智慧校园&#xff0c;这一融合了物联网、大数据、云计算等先进技术的教育新形态&#xff0c;正逐步成为高校转型升级的关键驱动力。本文将从多个维…

【题解】AB33 相差不超过k的最多数(排序 + 滑动窗口)

https://www.nowcoder.com/practice/562630ca90ac40ce89443c91060574c6?tpId308&tqId40490&ru/exam/oj 排序 滑动窗口 #include <iostream> #include <vector> #include <algorithm> using namespace std;int main() {int n, k;cin >> n &…

【Java】/*类和对象(下)*/

目录 一、封装 1.1 初识封装 1.2 如何封装成员变量 1.3 如何使用封装后的成员变量 二、访问限定符 三、包 3.1 包的概念 3.2 如何自定义包 3.3 导入包中的类 3.4 包的访问权限控制举例 示例一&#xff1a;private修饰成员变量 示例二&#xff1a; 不去修饰成员变…

有容量限制的车辆路径规划问题(Capacitated Vehicle Routing Problem)

在看matlab的时候发现了这篇文章https://www.frontiersin.org/articles/10.3389/fict.2019.00013/full 仔细阅读一下。(英语渣渣&#xff0c;自学用) The Capacitated Vehicle Routing Problem (CVRP) is an NP-optimization problem (NPO) that has been of great interest …

秋招突击——算法打卡——5/24——无重复字符的最长字串

题目描述 实现代码 // 无重复字符的最长子串 int lengthOfLongestSubstring(string s) {int l 0,r 0;int res 0;unordered_map<char,int> temp;while(l < s.size()){temp[s.at(l)] l;for (r l 1; r < s.size() ; r) {if(temp.count(s.at(r))) break;else te…

CTF网鼎杯2020朱雀组 thinkjava思路记录

1.代码分析 BUUCTF在线评测 (buuoj.cn)打开ctf赛题之后&#xff0c;下载class文件&#xff0c;这个部分是不完整点的源码 在sqldict中存在一个sql注入点&#xff0c;没有采用java的预编译&#xff0c;调用了这个的是在test中&#xff0c;同时&#xff0c;这个采用了swagger接口…

基于 Faster-RCNN 的水稻叶片病害检测方法研究

1 前言 本次分享是使用基于 Faster-RCNN 的水稻叶片病害检测的深度学习算法研究&#xff0c;也是我研究的课题&#xff0c;本文本文使用的算法架构为 Faster R-CNN&#xff0c;研究的课题为使用两种不同的主干特征提取网ResNet-50 和VGG-16 模型进行模型训练和对比评估那…