3.QT-信号和槽|自定义槽函数|自定义信号}自定义的语法}带参数的信号和槽(C++)

news2025/5/10 13:06:41

信号和槽

Linux信号 Signal 系统内部的通知机制. 进程间通信的方式.

  1. 信号源:谁发的信号.
  2. 信号的类型:哪种类别的信号
  3. 信号的处理方式:注册信号处理函数,在信号被触发的时候自动调用执行.

Qt中的信号和Linux中的信号,虽然不是一样的概念,但是确实有相似之处

Qt中,谈到信号,也是涉及到三个要素信号源:

  1. 由哪个控件发出的信号
  2. 信号的类型:用户进行不同的操作,就可能触发不同的信号
  • 点击按钮,触发点击信号.
  • 在输入框中移动光标,触发移动光标的信号,勾选一个复选框
  • 选择一个下拉框都会触发出不同的信号
    咱们写的GUI程序,就是要让用户进行操作.就是要和用户进行交互这个过程中就需要关注,用户当前的操作具体是个什么样的操作
  1. 信号的处理方式:槽(slot)=>函数
    Qt中可以使用connect这样的函数,把一个信号和一个槽关联起来后续只要信号触发了,Qt就会自动的执行槽函数

所谓的"槽函数"本质上也是一种"回调函数"(callback)
最早C语言阶段
C 进阶=>指针进阶=>函数指针.

  1. 实现转移表,降低代码的"圈复杂度”.
  2. 实现回调函数效果=〉qsort

后来在C++阶段~

  1. STL中,函数对象/仿函数
  2. lambda 表达式.

后来在Linux中

  1. 信号处理函数
  2. 线程的入口函数.
  3. epoll基于回调的机制

一定是先把信号的处理方式准备好,再触发信号~
Qt中,一定是先关联号信号和槽,然后再触发这个信号.顺序不能颠倒,否则信号就不知道如何处理了(错过了).

信号和槽概述

在Qt中,⽤⼾和控件的每次交互过程称为⼀个事件。⽐如"⽤⼾点击按钮"是⼀个事件,"⽤⼾关闭窗⼝"也是⼀个事件。每个事件都会发出⼀个信号,例如⽤⼾点击按钮会发出"按钮被点击"的信号,⽤⼾关闭窗⼝会发出"窗⼝被关闭"的信号。
Qt中的所有控件都具有接收信号的能⼒,⼀个控件还可以接收多个不同的信号。对于接收到的每个信号,控件都会做出相应的响应动作。例如,按钮所在的窗⼝接收到"按钮被点击"的信号后,会做出"关闭⾃⼰"的响应动作;再⽐如输⼊框⾃⼰接收到"输⼊框被点击"的信号后,会做出"显⽰闪烁的光标,等待⽤⼾输⼊数据"的响应动作。在Qt中,对信号做出的响应动作就称之为槽。
信号和槽是Qt特有的消息传输机制,它能将相互独⽴的控件关联起来。⽐如,"按钮"和"窗⼝"本⾝是两个独⽴的控件,点击"按钮"并不会对"窗⼝"造成任何影响。通过信号和槽机制,可以将"按钮"和"窗⼝"关联起来,实现"点击按钮会使窗⼝关闭"的效果。
![[Pasted image 20250417183130.png]]

信号的本质

信号是由于⽤⼾对窗⼝或控件进⾏了某些操作,导致窗⼝或控件产⽣了某个特定事件,这时Qt对应的窗⼝类会发出某个信号,以此对⽤⼾的操作做出反应。因此,信号的本质就是事件。如:

  • 按钮单击、双击
  • 窗⼝刷新
  • ⿏标移动、⿏标按下、⿏标释放
  • 键盘输⼊
    那么在Qt中信号是通过什么形式呈现给使⽤者的呢?
  • 我们对哪个窗⼝进⾏操作,哪个窗⼝就可以捕捉到这些被触发的事件。
  • 对于使⽤者来说触发了⼀个事件我们就可以得到Qt框架给我们发出的某个特定信号。
  • 信号的呈现形式就是函数,也就是说某个事件产⽣了,Qt框架就会调⽤某个对应的信号函数,通知使⽤者。
    在Qt中信号的发出者是某个实例化的类对象。
槽的本质

槽(Slot)就是对信号响应的函数。槽就是⼀个函数,与⼀般的C++函数是⼀样的,可以定义在类的任何位置(public、protected或private),可以具有任何参数,可以被重载,也可以被直接调⽤(但是不能有默认参数)。槽函数与⼀般的函数不同的是:槽函数可以与⼀个信号关联,当信号被发射时,关联的槽函数被⾃动执⾏。
说明
(1)信号和槽机制底层是通过函数间的相互调⽤实现的。每个信号都可以⽤函数来表⽰,称为信号函数;每个槽也可以⽤函数表⽰,称为槽函数。例如:"按钮被按下"这个信号可以⽤clicked()函数表⽰,"窗⼝关闭"这个槽可以⽤close()函数表⽰,假如使⽤信号和槽机制-实现:"点击按钮会关闭窗⼝"的功能,其实就是clicked()函数调⽤close()函数的效果。
(2)信号函数和槽函数通常位于某个类中,和普通的成员函数相⽐,它们的特别之处在于:

  • 信号函数⽤signals关键字修饰,槽函数⽤public slots、protected slots 或者private slots修 饰。signals和slots是Qt在C++的基础上扩展的关键字,专⻔⽤来指明信号函数和槽函数;
  • 信号函数只需要声明,不需要定义(实现),⽽槽函数需要定义(实现)。
    信号函数的定义是Qt⾃动在编译程序之前⽣成的.编写Qt应⽤程序的程序猿⽆需关注.
    这种⾃动⽣成代码的机制称为元编程(Meta Programming).这种操作在很多场景中都能⻅到.

信号和槽的使⽤

连接信号和槽

在Qt中,QObject类提供了⼀个静态成员函数connect(),该函数专⻔⽤来关联指定的信号函数和槽函数
QObject是Qt内置的⽗类.Qt中提供的很多类都是直接或者间接继承⾃QObject.

connect()函数原型:

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

参数说明:

  • sender:信号的发送者;(哪个控件)
  • signal:发送的信号(信号函数);(信号的类型)
  • receiver:信号的接收者;(控件)
  • method:接收信号的槽函数;(要处理信号的对象提供的成员函数)
  • type:⽤于指定关联⽅式,默认的关联⽅式为Qt::AutoConnection,通常不需要⼿动设定

代码⽰例:在窗⼝中设置⼀个按钮,当点击"按钮"时关闭"窗⼝"。

#include "widget.h"
#include "ui_widget.h"
  
#include <QPushButton>
  
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
  
    QPushButton* button = new QPushButton(this);
    button->setText("关闭");
    button->move(200, 200);
  
    connect(button, &QPushButton::clicked, this, &Widget::close);
}
  
Widget::~Widget()
{
    delete ui;
}

所谓的信号也就是Qt中的对象,内部提供的一些成员函数
![[Pasted image 20250417185911.png]]

图标带有锯齿,slot函数,click是一个slot函数,作用就是在调用的时候相当于点击了一下按钮
带有类似wifi的图标,就是信号函数,clicked,才是要触发的点击信号

button, &QPushButton::clicked

connect函数要求,这俩参数是匹配的,button的类型如果是QPushButton*,此时第二个参数的信号必须是QPushButton内置的信号或者父类的信号,不能是其他的类的信号

this, &Widget::close

close是QWidget内置的槽函数,Widget继承自QWidget,也就继承了父亲的槽函数
close槽函数功能已经是内部实现好的,具体作用就是关闭当前的窗口/控件

connect(button, &QPushButton::clicked, this, &Widget::close);

针对button,进行点击操作,Widget就会关闭
![[Pasted image 20250417194027.png]]

具体可以查看Qt文档
![[Pasted image 20250417194426.png]]

connect中的char*参数
但是传入的是&QPushButton::clicked, &Widget::close函数指针
![[Pasted image 20250417201211.png]]

void(*)();
![[Pasted image 20250417201234.png]]

bool(*)();
这两个函数指针的类型也是不同的
![[Pasted image 20250417201402.png]]

这个函数声明,是以前l日版本的Qt的connect函数的声明
以前版本中,传参的写法和现在其实也是有区别的此时,给信号参数传参,要搭配一个SIGNAL宏. 给槽参数传参,搭配一个SLOT宏.
传入的函数指针转成char*

connect(button, SIGNAL(&QPushButton::clicked), this, SLOT(&Widget::close));

Qt 5开始,对上述写法做出了简化.不再需要写SIGNAL 和SLOT宏了.
给connect提供了重载版本.重载版本中,第二个参数和第四个参数成了泛型参数.允许咱们传入任意类型的函数指针了.
![[Pasted image 20250417201637.png]]

QtPrivate::FunctionPointer<Func1>::ObjectQt封装的类型萃取器
此时connect函数就带有了一定的参数检查功能
如果你传入的第一个参数和第二个参数不匹配,或者第三个参数和第四个参数不匹配.(不匹配,2,4参数的函数指针,不是1,3 参数的成员函数)
此时代码编译出错

自定义槽函数1

widget.cpp

#include "widget.h"
#include "ui_widget.h"
  
#include <QPushButton>
  
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
  
    QPushButton* button = new QPushButton(this);
    button->setText("按钮");
    button->move(100, 100);
  
    connect(button, &QPushButton::clicked, this, &Widget::handleClicked);
}
  
Widget::~Widget()
{
    delete ui;
}
  
void Widget::handleClicked()
{
    //按下按钮,修改窗口标题
    this->setWindowTitle("按钮已经按下");
}

widget.h

#ifndef WIDGET_H
#define WIDGET_H
  
#include <QWidget>
  
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
  
class Widget : public QWidget
{
    Q_OBJECT
  
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
  
    void handleClicked();
  
private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

![[Pasted image 20250417202721.png]]

按下按钮
![[Pasted image 20250417202729.png]]

所谓的slot就是一个普通的成员函数
所谓的自定义一个槽函数,操作过程和自定义一个普通的成员函数,没啥区别!在以前版本的Qt中,槽函数必须放到public/private/protected slots:
![[Pasted image 20250417203313.png]]

此处的slots是Qt自己扩展的关键字.(不是C++标准中的语法) Qt里广泛使用了元编程技术. (基于代码,生成代码)
qmake 构建Qt项目的时候,就会调用专门的扫描器,扫描代码中特定的关键字.(slots这种) 基于关键字自动生成一大堆相关的代码,

自定义槽函数2

图形化方式拖入一个PushButton
![[Pasted image 20250417203641.png]]

鼠标右键点击PushButton
![[Pasted image 20250417203929.png]]

点击转到槽
![[Pasted image 20250417203939.png]]

这个窗口列出了QPushButton提供的所有信号,包含了QPushButton父类的信号
双击clicked
![[Pasted image 20250417204153.png]]

直接生成好了一个函数,声明也生成好了
可以直接编写代码

void Widget::on_pushButton_clicked()
{
    this->setWindowTitle("按钮已经按下");
}

![[Pasted image 20250417204315.png]]

在Qt中,除了通过connect来连接信号槽之外,还可以通过函数名字的方式来自动连接

void Widget::on_pushButton_clicked()

⾃动⽣成槽函数的名称有⼀定的规则。槽函数的命名规则为:on_XXX_SSS,其中:

  1. 以"on"开头,中间使⽤下划线连接起来;
  2. "XXX"表⽰的是对象名(控件的 objectName 属性)。
  3. "SSS"表⽰的是对应的信号。
    如:“on_pushButton_clicked()”,pushButton代表的是对象名,clicked是对应的信号。
    ![[Pasted image 20250417205652.png]]

Qt中调用这个函数的时候,就会触发上述自动连接信号槽的规则!!正是在自动生成的ui_widget.h中调用的~
![[Pasted image 20250417205720.png]]

如果我们通过图形化界面创建控件,还是推荐使用这种快速的方式来连接信号槽
如果我们是通过代码的方式来创建控件,还是得手动connect.(你的代码中没有调用connectSlotsByName)

自定义信号

Qt中也充许自定义信号
自定义槽函数,非常关键.开发中大部分情况都是需要自定义槽函数的槽函数,就是用户触发某个操作之后,要进行的业务逻辑
自定义信号,比较少见.实际开发中很少会需要自定义信号.
信号就对应到用户的某个操作~
在GUI,用户能够进行哪些操作,是可以穷举的~~
Qt内置的信号,基本上已经覆盖到了上述所有可能的用户操作
因此,使用Qt内置的信号,就足以应付大部分的开发场景了,
自定义信号,本身代码比较简单的~
![[Pasted image 20250417211348.png]]

Widget虽然还没有定义任何信号,由于继承自QWidget,和QObject,这俩类里面已经提供了一些信号了,可以直接使用.
所谓的Qt的信号,本质上也就是一个"函数
Qt5以及更高版本中,槽函数和普通的成员函数之间,没啥差别了. 但是,信号,则是一类非常特殊的函数,

  1. 程序员只要写出函数声明,并且告诉Qt,这是一个“信号”即可, 1.
    这个函数的定义,是Qt在编译过程中,自动生成的.(自动生成的过程,程序员无法干预)
    信号在Qt中是特殊的机制.Qt生成的信号函数的实现,要配合Qt框架做很多既定的操作~~
  2. 作为信号函数,这个函数的返回值,必须是void.
    有没有参数都可以.甚至也可以支持重载
    ![[Pasted image 20250417211440.png]]

这个也是Qt自己扩展出来的关键字~~
qmake的时候,调用一些代码的分析/生成工具,
扫描到类中包含signals这个关键字的时候,此时,就会自动的把下面的函数声明认为是信号,并且给这些信号函数自动的生成函数定义
widget.h

#ifndef WIDGET_H
#define WIDGET_H
  
#include <QWidget>
  
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
  
class Widget : public QWidget
{
    Q_OBJECT
  
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
signals:
    void mySignal();
public slots:
    void handleMySignal();
  
private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"
  
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    connect(this, &Widget::mySignal, this, &Widget::handleMySignal);

    //发送自定义信号
    emit mySignal();
}
  
Widget::~Widget()
{
    delete ui;
}
  
void Widget::handleMySignal()
{
    this->setWindowTitle("处理自定义信号");
}

如何才能触发出自定义的信号呢?
Qt内置的信号,都不需要咱们手动通过代码来触发
用户在GUI,进行某些操作,就会自动触发对应信号.(发射信号的代码已经内置到Qt框架中了)
自定义的信号需要通过emit,来发射信号

emit mySignal();

![[Pasted image 20250417212346.png]]

在启动的时候直接触发信号
发送信号的操作,可以在任何合适的代码中,不一定非要在构造函数中

#include "widget.h"
#include "ui_widget.h"
  
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
  
    connect(this, &Widget::mySignal, this, &Widget::handleMySignal);
  
  
}
  
Widget::~Widget()
{
    delete ui;
}
  
void Widget::handleMySignal()
{
    this->setWindowTitle("处理自定义信号");
}
  
  
void Widget::on_pushButton_clicked()
{
    //发送自定义信号
    emit mySignal();
}

通过图形化方式创建一个槽函数
![[Pasted image 20250417212730.png]]

点击按钮
![[Pasted image 20250417212736.png]]

点击按钮->
QPushButton::clicked->
Widget::on_pushButton_clicked()->
emit mySignal();->
void Widget::handleMySignal()

其实在Qt5中emit 现在啥都没做
真正的操作都包含在mySignal内部生成的函数定义了
emit mySignal();
即使不写emit,信号也能发出去!!
即使如此,实际开发中,还是建议大家,把emit都加上
加上代码可读性更高,更明显的标识出,这里是发射自定义的信号了.

自定义的基本语法

在Qt中,允许⾃定义信号的发送⽅以及接收⽅,即可以⾃定义信号函数和槽函数。但是对于⾃定义的
信号函数和槽函数有⼀定的书写规范。
1、⾃定义信号函数书写规范

  1. ⾃定义信号函数必须写到"signals"下;
  2. 返回值为void,只需要声明,不需要实现;
  3. 可以有参数,也可以发⽣重载;

2、⾃定义槽函数书写规范

  1. 早期的Qt版本要求槽函数必须写到"public slots"下,但是现在⾼级版本的Qt允许写到类的"public"作⽤域中或者全局下;
  2. 返回值为void,需要声明,也需要实现;
  3. 可以有参数,可以发⽣重载;

3、发送信号
使⽤"emit"关键字发送信号。"emit"是⼀个空的宏。"emit"其实是可选的,没有什么含义,只是为了提醒开发⼈员。

![[Pasted image 20250417213623.png]]

必须先关联再发射
原因是,⾸先关联信号和槽,⼀旦检测到信号发射之后就会⽴⻢执⾏关联的槽函数。反之,若先发射信号,此时还没有关联槽函数,当信号发射之后槽函数不会响应

带参数的信号和槽

Qt的信号和槽也⽀持带有参数,同时也可以⽀持重载.
此处我们要求,信号函数的参数列表要和对应连接的槽函数参数列表⼀致.
此时信号触发,调⽤到槽函数的时候,信号函数中的实参就能够被传递到槽函数的形参当中

signals:
    void mySignal(const QString& text);
  
public slots:
    void handleMySignal(const QString& text);

这里的参数必须一致
一致主要是要求类型一致,个数如果不一致也可以,不一致的时候,信号的参数的个数必须比槽的参数的个数更多

void Widget::handleMySignal(const QString& text)
{
    this->setWindowTitle(text);
}
  
  
void Widget::on_pushButton_clicked()
{
    //发送自定义信号
    emit mySignal("带参数的信号");
}

![[Pasted image 20250417215916.png]]

点击按钮
![[Pasted image 20250417215923.png]]

传参可以起到复用代码的效果
有多个逻辑,逻辑上整体一致,但是涉及到的数据不同,
就可以通过函数-参数来复用代码,并且在不同的场景中传入不同的参数即可~
![[Pasted image 20250417220231.png]]

新建一个PushButton
转到槽,新建一个clicked函数

void Widget::on_pushButton_clicked()
{
    //发送自定义信号
    emit mySignal("把标题设置为标题1");
}
  
void Widget::on_pushButton_2_clicked()
{
    emit mySignal("把标题设置为标题2");
}

![[Pasted image 20250417220435.png]]

![[Pasted image 20250417220440.png]]

通过这一套信号槽,搭配不同的参数,就可以起到设置不同标题的效果

Qt中很多内置的信号,也是带有参数的.(这些参数不是咱们自己传递的)
clicked信号就带有一个参数~~
![[Pasted image 20250417221013.png]]

这个参数表示当前按钮是否处于“选中”状态这个选中状态对于QPushButton没啥意义,对于QCheckBox复选框,就很有用了,

signals:
    void mySignal(const QString& text, const QString& text2);
  
public slots:
    void handleMySignal(const QString& text);
void Widget::on_pushButton_clicked()
{
    //发送自定义信号
    emit mySignal("把标题设置为标题1", "");
}
  
void Widget::on_pushButton_2_clicked()
{
    emit mySignal("把标题设置为标题2", "");
}

信号函数的参数个数,超过了槽函数的参数个数,此时,都是可以正常使用的信号函数的参数个数,少于槽函数的参数个数,此时代码无法编译通过
![[Pasted image 20250417222042.png]]

直观的思考,应该是要求信号的参数个数和槽的参数个数,严格一致
此处为啥允许信号的参数比槽的参数多呢?? 一个槽函数,有可能会绑定多个信号
如果我们严格要求参数个数一致,就意味着信号绑定到槽的要求就变高了,
换而言之,当下这样的规则,就允许信号和槽之间的绑定更灵活了,更多的信号可以绑定到这个槽函数上了,
个数不一致,槽函数就会按照参数顺序,拿到信号的前N个参数
至少需要确保,槽函数的每个参数都是有值的
要求信号给槽的参数,可以有富裕,但是不能少
![[Pasted image 20250417222334.png]]

![[Pasted image 20250417222340.png]]

![[Pasted image 20250417222418.png]]

带有参数的信号,要求信号的参数和槽的参数要一致
类型,个数要满足要求(信号的参数个数要多于槽的参数个数).

widget.h
![[Pasted image 20250417222531.png]]

Qt中如果要让某个类能够使用信号槽(可以在类中定义信号和槽函数)
则必须要在类最开始的地方,写下QOBJECT宏
这个宏能展开成很多额外的代码
![[Pasted image 20250417222727.png]]

如果不加这个宏,这个类编译的时候会报错

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

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

相关文章

健康养生之道

在快节奏的现代生活中&#xff0c;健康养生不再是中老年人的专属话题&#xff0c;越来越多的人开始意识到&#xff0c;合理的养生方式是保持良好身体状态和生活质量的关键。​ 饮食养生是健康的基石。遵循 “食物多样、谷类为主” 的原则&#xff0c;保证每天摄入足够的蔬菜、…

Spark-SQL核心编程3

数据加载与保存 通用方式&#xff1a; SparkSQL 提供了通用的保存数据和数据加载的方式。这里的通用指的是使用相同的API&#xff0c;根据不同的参数读取和保存不同格式的数据&#xff0c;SparkSQL 默认读取和保存的文件格式为parquet 数据加载方法&#xff1a; spark.read.lo…

TVM计算图分割--Collage

1 背景 为满足高效部署的需要&#xff0c;整合大量优化的tensor代数库和运行时做为后端成为必要之举。现在的深度学习后端可以分为两类&#xff1a;1&#xff09;算子库(operator kernel libraries)&#xff0c;为每个DL算子单独提供高效地低阶kernel实现。这些库一般也支持算…

MCGS昆仑通太屏笔记

4.3寸&#xff1a;4013ef/e1 7寸&#xff1a;7032kw 特点&#xff1a; 如果是使用组态屏进行调试使用&#xff0c;选择com1如果是实际项目使用&#xff0c;选择com2 操作步骤&#xff1a; 先创建设备窗口&#xff0c;再创建用户界面 在设备窗口界面&#xff0c;依次设置如下…

服务治理-搭建Nacos注册中心

运行nacos.sql文件。 将准备好的nacos目录和nacos.tar包上传。 192.168.59.101是我的虚拟机ip&#xff0c;8848是我们设置的访问端口号。

网络--socket编程(2)

Socket 编程 TCP TCP 网络程序 和刚才 UDP 类似 . 实现一个简单的英译汉的功能 TCP socket API 详解 下面介绍程序中用到的 socket API, 这些函数都在 sys/socket.h 中。 socket(): • socket() 打开一个网络通讯端口 , 如果成功的话 , 就像 open() 一样返回一个…

结合建筑业务讲述TOGAF标准处理哪种架构

TOGAF标准处理哪种架构 内容介绍业务架构业务策略&#xff0c;治理&#xff0c;组织和关键业务流程数据架构组织的逻辑和物理数据资产以及数据管理资源的结构应用架构待部署的各个应用程序&#xff0c;它们之间的交互以及与组织核心业务流程的关系的蓝图技术架构支持业务&#…

C++入门小馆: 深入string类(一)

嘿&#xff0c;各位技术潮人&#xff01;好久不见甚是想念。生活就像一场奇妙冒险&#xff0c;而编程就是那把超酷的万能钥匙。此刻&#xff0c;阳光洒在键盘上&#xff0c;灵感在指尖跳跃&#xff0c;让我们抛开一切束缚&#xff0c;给平淡日子加点料&#xff0c;注入满满的pa…

NHANES指标推荐:WWI

文章题目&#xff1a;Weight-adjusted waist circumference index with hepatic steatosis and fibrosis in adult females: a cross-sectional, nationally representative study (NHANES 2017-2020) DOI&#xff1a;10.1186/s12876-025-03706-4 中文标题&#xff1a;体重调整…

2025.04.18|【Map】地图绘图技巧全解

Add circles Add circles on a Leaflet map Change tile Several background tiles are offered by leaflet. Learn how to load them, and check the possibilities. 文章目录 Add circlesChange tile 2025.04.18【Map】| 地图绘图技巧全解1. 准备工作2. 地理区域着色图&…

PR第一课

目录 1.新建 2.PR内部设置 3.导入素材 4.关于素材窗口 5.关于编辑窗口 6.序列的创建 7.视频、图片、音乐 7.1 带有透明通道的素材 8.导出作品 8.1 打开方法 8.2 导出时&#xff0c;需要修改的参数 1.新建 2.PR内部设置 随意点开 编辑->首选项 中的任意内容&a…

Vue+Notification 自定义消息通知组件 支持数据分页 实时更新

效果图&#xff1a; message.vue 消息组件 子组件 <template><div class"custom-notification"><div class"content"><span click"gotoMessageList(currentMessage.split()[1])">{{ currentMessage.split()[0] }}</…

不规则曲面上两点距离求取

背景 在CT中求皮肤上两点间的弧长。由于人体表面并不是规则的曲面&#xff0c;不可能用圆的弧长求取方法来计算出两点间的弧长。 而在不规则的曲面上求两点的距离&#xff0c;都可以用类似测地线距离求取的方式来求取&#xff08;积分&#xff09;&#xff0c;而转化为搜索路…

性能比拼: Elixir vs Go

本内容是对知名性能评测博主 Anton Putra Elixir vs Go (Golang) Performance (Latency - Throughput - Saturation - Availability) 内容的翻译与整理, 有适当删减, 相关指标和结论以原作为准 对比 Elixir 和 Go 简介 许多人长期以来一直要求我对比 Elixir 和 Go。在本视频…

【Linux网络与网络编程】11.数据链路层mac帧协议ARP协议

前面在介绍网络层时我们提出来过一个问题&#xff1a;主机是怎么把数据交给路由器的&#xff1f;那里我们说这是由数据链路层来做的。 网络上的报文在物理结构上是以mac帧的形式流动的&#xff0c;但在逻辑上是以IP流动的&#xff0c;IP的流动是需要mac帧支持的。 数据链路层解…

lottie深入玩法

A、json文件和图片资源分开 delete 是json资源名字 /res/lottie/delete_anim_images是图片资源文件夹路径 JSON 中引用的图片名&#xff0c;必须与实际图片文件名一致 B、json文件和图片资源分开&#xff0c;并且图片加载不固定 比如我有7张图片&#xff0c;分别命名1~7&…

热门与冷门并存,25西电—电子工程学院(考研录取情况)

1、电子工程学院各个方向 2、电子工程学院近三年复试分数线对比 学长、学姐分析 由表可看出&#xff1a; 1、电子科学与技术25年相较于24年上升20分 2、信息与通信工程、控制科学与工程、新一代电子信息技术&#xff08;专硕&#xff09;25年相较于24年下降25分 3、25vs24推…

Warcraft Logs [Classic] [WCL] BOSS ID query

Warcraft Logs [Classic] [WCL] BOSS ID query 所有副本BOSSID查询 https://wowpedia.fandom.com/wiki/DungeonEncounterID#Retail IDNameMapInstanceIDPatch227High Interrogator GerstahnBlackrock Depths230228Lord RoccorBlackrock Depths230229Houndmaster GrebmarBlackro…

架构师面试(三十一):IM 消息收发逻辑

问题 今天聊一下 IM 系统最核心的业务逻辑。 在上一篇短文《架构师面试&#xff08;三十&#xff09;&#xff1a;IM 分层架构》中详细分析过&#xff0c;IM 水平分层架构包括&#xff1a;【入口网关层】、【业务逻辑层】、【路由层】和【数据访问层】&#xff1b;除此之外&a…

基于若依框架前后端分离的项目部署

文章目录 单项目的部署项目目录后端打包上传前端打包上传配置nginx服务器打开防火墙完成 两个项目的部署两个项目介绍后端打包并上传前端打包并上传nginx配置服务器端口开放完成 腾讯云服务器 之 环境搭建 单项目的部署 项目目录 后端打包上传 查看端口号 在ruoyi-admin的appl…