Qt--信号和槽

news2024/10/5 14:15:12

写在前面

信号与槽机制是Qt中最重要的特性之一,也是其与其他GUI框架的主要区别之一。信号与槽机制允许不同对象之间进行通信和交互,从而实现程序的模块化和可重用性。

在Qt中,信号是一种事件,它可以被任何对象接收并执行相应的操作。信号通常由一个字符串参数组成,用于描述信号所关联的操作。例如,一个按钮被点击时会发出一个clicked()信号,一个文本框内容改变时会发出textChanged()信号等。

槽是一种与信号相关联的方法,它是一个无参数的虚函数。当某个对象接收到与其相关的信号时,它会自动调用与之关联的槽函数。槽函数可以执行任何操作,包括修改对象的状态、更新视图等。例如,当一个按钮被点击时,程序会自动调用按钮的clicked()槽函数。

通过使用信号与槽机制,Qt应用程序可以实现以下功能:

①实现对象之间的通信和交互。
②实现模块化和可重用性。
③支持多线程编程。
④支持自定义控件和插件。

connect

Qt中的connect函数用于将信号和槽连接起来,使得当信号被发射时,槽函数会被自动调用。

connect函数的语法如下:

QMetaObject::Connection 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。

connect函数返回一个QMetaObject::Connection对象,该对象表示连接的关系。可以使用该对象进行断开连接等操作。

connect简单示例

这里创建一个QWidget应用程序,在Widget中添加一个按钮,实现点击该按钮关闭整个窗口的功能。

核心代码如下:

#include "widget.h"
#include "mypushbutton.h"
#include <QDebug>
#include <QPushButton>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    MyPushButton* myBtn = new MyPushButton(this);
    myBtn->setText("我的按钮");
    myBtn->move(0, 100);

    //信号和槽基本使用
    connect(myBtn, &MyPushButton::clicked, this, &QWidget::close);

}

Widget::~Widget()
{
    qDebug() << "Widget 析构函数";
}

自定义信号和槽

在Qt中,若窗口或控件当前的信号和槽不满足自己的需求,或者想使自己定义的类拥有其特有的信号和槽,Qt是支持使用自定义的信号和槽的。

自定义信号和槽,需注意:
①自定义信号和槽的类需继承自 QObject。自定义信号和槽必须继承自 QObject,因为它们是 Qt 元对象系统的一部分。
②使用 Q_OBJECT 宏。为了使自定义信号和槽能够在运行时调用其 metaObject() 方法,必须在类的头文件中使用 Q_OBJECT 宏进行标记。

自定义信号

自定义信号,需要注意以下几点:
①自定义信号需要在signals:限定符下声明
②自定义信号只需声明,无需实现
③自定义信号可以有参数,可以重载。这里下面会单独介绍

自定义槽

自定义槽函数,需要注意以下几点:
①需在public slots:下声明
②返回值为void
③需要声明,也需要实现
④可以有参数,可以重载。这里下面会单独介绍

这里实现一个简单的无参的自定义信号和槽的应用。新建一个DIYSignal和DIYSlot类,为支持自定义信号和槽,这两个类都需继承自QObject类。

添加后的工程文件内容如下:

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    diysignal.cpp \
    diyslot.cpp \
    main.cpp \
    mypushbutton.cpp \
    widget.cpp

HEADERS += \
    diysignal.h \
    diyslot.h \
    mypushbutton.h \
    widget.h

在DIYSignal类的signal: 限定符下声明我们的自定义信号:

#ifndef DIYSIGNAL_H
#define DIYSIGNAL_H

#include <QObject>

class DIYSignal : public QObject
{
    Q_OBJECT
public:
    explicit DIYSignal(QObject *parent = nullptr);

signals:
    //自定义信号
    void mySignal();

};

#endif // DIYSIGNAL_H

因为信号只需声明无需实现,因此这里省略DIYSignal.cpp的代码。

在DIYSlot类的public slots: 限定符下声明自定义槽函数:

#ifndef DIYSLOT_H
#define DIYSLOT_H

#include <QObject>

class DIYSlot : public QObject
{
    Q_OBJECT
public:
    explicit DIYSlot(QObject *parent = nullptr);

signals:

public slots:
	//自定义槽函数
    void mySlot();

};

#endif // DIYSLOT_H

在DIYSlot.cpp中实现自定义槽函数:

#include "diyslot.h"
#include <QDebug>

DIYSlot::DIYSlot(QObject *parent)
    : QObject{parent}
{

}

void DIYSlot::mySlot()
{
    qDebug() << "响应自定义信号,自定义槽函数";
}

void DIYSlot::mySlot(QString qsTips)
{
    qDebug() << "响应带参的自定义信号,带参自定义槽函数, 参数:" << qsTips;
}

然后在QWidget窗口的构造中自动连接触发自定义信号:

#include "widget.h"
#include "mypushbutton.h"
#include <QDebug>
#include <QPushButton>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    MyPushButton* myBtn = new MyPushButton(this);
    myBtn->setText("我的按钮");
    myBtn->move(0, 100);

    //信号和槽基本使用
    connect(myBtn, &MyPushButton::clicked, this, &QWidget::close);

    //自定义信号和槽
    m_pDIYSignal = new DIYSignal(this);
    m_pDIYSlot = new DIYSlot(this);
    //连接
    connect(m_pDIYSignal, &DIYSignal::mySignal, m_pDIYSlot, &DIYSlot::mySlot);
    //触发
    emit m_pDIYSignal->mySignal();
}

Widget::~Widget()
{
    qDebug() << "Widget 析构函数";
}

运行后可以看到自定义信号被触发后,相应的槽函数会被调用:
无参自定义信号和槽

重载时的自定义信号和槽

当自定义信号和槽有重载版本时,在connect连接时需要明确指出连接的信号和槽的版本。

例,这里添加重载的信号和槽版本:

DIYSignal.h如下:

#ifndef DIYSIGNAL_H
#define DIYSIGNAL_H

#include <QObject>

class DIYSignal : public QObject
{
    Q_OBJECT
public:
    explicit DIYSignal(QObject *parent = nullptr);

signals:
    //自定义信号
    void mySignal();
    //重载版本
    void mySignal(QString qsTips);

};

#endif // DIYSIGNAL_H

DIYSlot.h如下:

#ifndef DIYSLOT_H
#define DIYSLOT_H

#include <QObject>

class DIYSlot : public QObject
{
    Q_OBJECT
public:
    explicit DIYSlot(QObject *parent = nullptr);

signals:

public slots:
    //自定义槽函数
    void mySlot();
    //重载版本
    void mySlot(QString qsTips);

};

#endif // DIYSLOT_H

DIYSlot.cpp如下:

#include "diyslot.h"
#include <QDebug>

DIYSlot::DIYSlot(QObject *parent)
    : QObject{parent}
{

}

void DIYSlot::mySlot()
{
    qDebug() << "响应自定义信号,自定义槽函数";
}

void DIYSlot::mySlot(QString qsTips)
{
    qDebug() << "响应带参的自定义信号,带参自定义槽函数, 参数:" << qsTips;
}

如果还想之前那样连接,编译器就无法得到这里连接的是哪个信号和槽:

//自定义信号和槽
m_pDIYSignal = new DIYSignal(this);
m_pDIYSlot = new DIYSlot(this);
//连接
connect(m_pDIYSignal, &DIYSignal::mySignal, m_pDIYSlot, &DIYSlot::mySlot);
//触发
emit m_pDIYSignal->mySignal();

编译会报错提示:
重载自定义信号和槽连接报错

因此这里需明确指定信号和对应的槽函数版本:

    //自定义信号和槽
    m_pDIYSignal = new DIYSignal(this);
    m_pDIYSlot = new DIYSlot(this);
    //连接
    void (DIYSignal::*mySignalFun)() = &DIYSignal::mySignal;
    void (DIYSlot::*mySlotFun)() = &DIYSlot::mySlot;
    connect(m_pDIYSignal, mySignalFun, m_pDIYSlot, mySlotFun);
    //触发
    emit m_pDIYSignal->mySignal();

    //自定义信号和槽有重载版本时,连接需要明确指出重载的版本
    void (DIYSignal::*mySignalFunWithArg)(QString) = &DIYSignal::mySignal;
    void (DIYSlot::*mySlotFunWithArg)(QString) = &DIYSlot::mySlot;
    connect(m_pDIYSignal, mySignalFunWithArg, m_pDIYSlot, mySlotFunWithArg);
    emit m_pDIYSignal->mySignal("tips");

使用函数指针明确重载版本,需要注意别忘了添加对应类的作用域。

运行后可以看到两个信号被触发,对应的槽函数会被调用:
重载版本的触发结果

自定义信号和槽的扩展

除了上面提到的重载时的情况,自定义信号和槽也还有以下扩展:
①信号可以连接信号
②一个信号可以连接到多个槽函数
③多个信号可以连接同一个槽函数
④信号和槽函数的参数,必须一一对应
⑤信号和槽函数的参数个数可以不同,但信号的参数个数必须多于槽函数的参数个数,且相等部分的参数类型必须一一对应(同第④点)
⑥可以使用Qt4版本以前的信号和槽的连接方式

下面将逐一举例介绍。

信号可以连接信号

Qt的信号和槽机制并没有强制要求信号只能和槽连接,也可以通过一个信号触发另一个信号。

上面示例中,都是程序运行后自动触发自定义信号,这里调整成点击按钮,来触发自定义信号。

//自定义信号和槽
    m_pDIYSignal = new DIYSignal(this);
    m_pDIYSlot = new DIYSlot(this);
    //连接
    void (DIYSignal::*mySignalFun)() = &DIYSignal::mySignal;
    void (DIYSlot::*mySlotFun)() = &DIYSlot::mySlot;
    connect(m_pDIYSignal, mySignalFun, m_pDIYSlot, mySlotFun);
    //触发
    //emit m_pDIYSignal->mySignal();

    //自定义信号和槽有重载版本时,连接需要明确指出重载的版本
    void (DIYSignal::*mySignalFunWithArg)(QString) = &DIYSignal::mySignal;
    void (DIYSlot::*mySlotFunWithArg)(QString) = &DIYSlot::mySlot;
    connect(m_pDIYSignal, mySignalFunWithArg, m_pDIYSlot, mySlotFunWithArg);
    //emit m_pDIYSignal->mySignal("tips");

    //信号连接信号
    QPushButton* myDiySigBtn = new QPushButton(this);
    myDiySigBtn->setText("触发无参自定义信号");
    connect(myDiySigBtn, &QPushButton::clicked, m_pDIYSignal, mySignalFun);

信号连接信号

一个信号可以连接到多个槽函数

一个信号可以连接到多个槽函数,但必须遵循上面的第④、⑤点,即自定义信号的参数必须大于等于槽函数的参数,且相等部分的参数类型需一一对应。

这里使用带参的自定义信号,分别连接无参和带参的槽函数。
ps:因为无参的自定义信号,不能连接带参的槽函数。不满足第⑤点信号的参数大于等于槽函数的参数个数条件。

    //自定义信号和槽
    m_pDIYSignal = new DIYSignal(this);
    m_pDIYSlot = new DIYSlot(this);
    //连接
    void (DIYSignal::*mySignalFun)() = &DIYSignal::mySignal;
    void (DIYSlot::*mySlotFun)() = &DIYSlot::mySlot;
    
    //自定义信号和槽有重载版本时,连接需要明确指出重载的版本
    void (DIYSignal::*mySignalFunWithArg)(QString) = &DIYSignal::mySignal;
    void (DIYSlot::*mySlotFunWithArg)(QString) = &DIYSlot::mySlot;

    //一个信号连接多个槽函数
    //带参信号连接无参槽函数
    connect(m_pDIYSignal, mySignalFunWithArg, m_pDIYSlot, mySlotFun);
    //带参信号连接带参槽函数
    connect(m_pDIYSignal, mySignalFunWithArg, m_pDIYSlot, mySlotFunWithArg);
    //自动触发
    emit m_pDIYSignal->mySignal("arg");

带参信号连接无参和带参的槽函数

多个信号连接同一个槽函数

不同对象的不同信号可以连接到同一槽函数,同样必须遵循上面的第④、⑤点,即自定义信号的参数必须大于等于槽函数的参数,且相等部分的参数类型需一一对应。

这里使用QPushButton的点击信号和无参(有参的也可以,因为满足④、⑤点条件)的自定义信号,连接无参的自定义槽函数。

//自定义信号和槽
    m_pDIYSignal = new DIYSignal(this);
    m_pDIYSlot = new DIYSlot(this);
    //连接
    void (DIYSignal::*mySignalFun)() = &DIYSignal::mySignal;
    void (DIYSlot::*mySlotFun)() = &DIYSlot::mySlot;
    
    //无参自定义信号 连接 无参槽函数
    connect(m_pDIYSignal, mySignalFun, m_pDIYSlot, mySlotFun);
    //触发
    emit m_pDIYSignal->mySignal();
	
	//QPushButton的点击信号 连接 无参的槽函数
	QPushButton* myDiySigBtn = new QPushButton(this);
    myDiySigBtn->setText("触发无参自定义槽函数");
    connect(myDiySigBtn, &QPushButton::clicked, m_pDIYSlot, mySlotFun);

结果如下:
多个信号连接同一槽函数

信号和槽函数的参数,必须一一对应

因为在信号触发时,调用已连接的槽函数,所以信号的参数会传递到槽函数的形参中。因此要求信号和槽函数的参数类型必须一一对象,否则就无法调用槽函数。

上面的示例中均有体现,这里就不再举例赘述。

信号和槽函数的参数个数可以不同,但信号的参数个数必须多于槽函数的参数个数,且相等部分的参数类型必须一一对应

信号的参数会逐一传递到槽函数参数中,但允许信号的参数多于槽函数的参数,相当于可以多传递参数给槽函数,但槽函数只接收自己对应的相等部分的参数即可。

不过这里需注意,信号和槽函数相等部分的参数,类型必须一一对应,以满足第④点的要求。

可以使用Qt4版本以前的信号和槽的连接方式

在存在重载版本的信号和槽函数时,在连接时需要通过声明函数指针来指定对应的重载版本,当重载版本过多时,工作量就会相应的增加。

因此可以考虑使用Qt4版本以前的信号和槽的连接方式,不仅不需要每个重载版本都声明一个对应的函数指针类型,而且还可以兼容Qt4版本开发的代码,因此推荐使用该方式连接信号和槽

该版本的连接方式,在connect函数的第二、四个参数使用SIGNAL、SLOT宏代替信号和槽函数的地址。

    //使用Qt4版本的信号和槽连接方式
    //连接无参信号和槽
    connect(m_pDIYSignal, SIGNAL(mySignal()), m_pDIYSlot, SLOT(mySlot()));
    //连接有参信号和槽
    connect(m_pDIYSignal, SIGNAL(mySignal(QString)), m_pDIYSlot, SLOT(mySlot(QString)));
    //触发
    emit m_pDIYSignal->mySignal();
    emit m_pDIYSignal->mySignal("tips");

运行结果如下:
Qt4版本之前的信号和槽的连接

总结

此次,Qt中的信号和槽机制已全部介绍完毕。

要想使自己定义的类支持信号和槽机制,需要满足以下两点:
①自定义信号和槽的类需继承自 QObject。自定义信号和槽必须继承自 QObject,因为它们是 Qt 元对象系统的一部分。
②使用 Q_OBJECT 宏。为了使自定义信号和槽能够在运行时调用其 metaObject() 方法,必须在类的头文件中使用 Q_OBJECT 宏进行标记。

声明自定义信号和槽时,需要注意以下几点:
自定义信号,需要注意以下几点:
①自定义信号需要在signals:限定符下声明
②自定义信号只需声明,无需实现
③自定义信号可以有参数,可以重载

自定义槽函数,需要注意以下几点:
①需在public slots:下声明
②返回值为void
③需要声明,也需要实现
④可以有参数,可以重载

使用自定义信号和槽时,需要注意以下几点:
①信号可以连接信号
②一个信号可以连接到多个槽函数
③多个信号可以连接同一个槽函数
④信号和槽函数的参数,必须一一对应
⑤信号和槽函数的参数个数可以不同,但信号的参数个数必须多于槽函数的参数个数,且相等部分的参数类型必须一一对应(同第④点)
⑥可以使用Qt4版本以前的信号和槽的连接方式

这里推荐使用Qt4版本之前的信号和槽的连接方式,connect时不仅清晰明了哪个版本的信号连接到哪个槽函数,而且还兼容之前使用Qt4开发的代码。

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

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

相关文章

Zookeeper、Nacos、Dubbo、Kafka之间的关系

1.Zookeeper Zookeeper 是 Apache Hadoop 的子项目&#xff0c;是一个树型的目录服务&#xff0c;支持变更推送&#xff0c;适合作为 Dubbo 服务的注册中心&#xff0c;工业强度较高。 Zookeeper的功能主要是它的树形节点来实现的。当有数据变化的时候或者节点过期的时候&…

AGV/AMR控制器--科聪

AGV/AMR控制器--科聪 1 行业介绍1.1 控制器概念1.2 行业发展1.3 竞争格局 2 科聪控制器 MRC50002.1 介绍2.2 支持多种导航方式2.3 适配各种轮系底盘2.4 核心参数2.5 优势灵活的二次开发平台&#xff1a;机器人设计软件&#xff08;xRobotStudio&#xff09;完备的实施调试工具&…

干货|写好论文,从一篇优秀的开题报告开始

Hello&#xff0c;大家好&#xff01; 这里是壹脑云科研圈&#xff0c;我是喵君姐姐~ 在今天的推文里&#xff0c;要给大家分享的是从开题报告到论文写作&#xff0c;快来一起看看哦~ 开题报告旨在总结与研究课题有关的立论依据、总体规划和预期研究成果&#xff0c;便于潜在…

一分钟带你了解网络安全(如何自学)

一、关于网络安全职业 早些年&#xff0c;网络安全刚起步&#xff0c;作为一个网络安全从业人员&#xff0c;最苦恼的事情就是每当回到村里变成狗蛋儿的时候&#xff0c;七大姑八大姨&#xff0c;邻里乡亲&#xff0c;村子里的各种人都会来找你&#xff0c;狗蛋儿&#xff0c;你…

(06)---STM32的Systick定时器与ADC

目录 【1】Systick定时器 概念 工作原理 时钟基准 【2】HAL_Delay函数分析 【3】定时器 基本概念 定时器分类 定时器组成 1.计数器 2.自动重装寄存器 3.预分频器 定时器计数原理 实验 2.PWM 定义 参数 工作原理 应用 练习&#xff1a;通过PWM信号调节LED灯亮度 练…

Convolutional Neural Network 的 PyTorch 实现(二)使用TensorRT进行推理加速

本文章针对 Windows 10 系统 目录 TensorRT 环境安装与配置zlibwapi.dll 安装与配置TensorRT 实现 CUDA CuDNN的安装&#xff1a; 参考文章 TensorRT 环境安装与配置 下载链接 TensorRT 本文章针对 Windows10、CUDA10.2 的PC&#xff0c;选择相对应的安装包完成下载。 解压后在…

迪赛智慧数——柱状图(基本柱状图):全球自动化无人机智能支出预测

效果图 全球自动化无人机智能支出及预测分析&#xff0c;2022年机器人流程自动化支出10.4十亿美元&#xff0c;智能流程自动化支出13十亿美元&#xff0c;人工智能业务操作达10.8十亿美元&#xff0c;未来&#xff0c;这些数字将进一步增长&#xff0c;自动化无人机智能也将拥有…

二战京东测试岗失败,真的后悔了....

两天&#xff0c;我的一个朋友去大厂面试&#xff0c;跟我聊天时说&#xff1a;输的很彻底… 我问她&#xff1a;什么情况&#xff1f; 她说&#xff1a;很后悔这5年来一直都干的是功能测试… 相信许多测试人也跟我朋友一样&#xff0c;从事了软件测试很多年&#xff0c;却依然…

小魔驼3.0下探至9万元背后,是毫末智行的“高位再进化”

作者 | 曾响铃 文 | 响铃说 是60分到90分难&#xff0c;还是90分到95分难&#xff1f; 这个问题不难回答——较高基数上的小幅度上升&#xff0c;要比较低基数上的大幅度上升困难得多。 这个道理在很多领域都十分适用&#xff0c;那些前沿技术领域更是如此&#xff0c;越到…

时钟、SysTick定时器、PWM、ADC

目录 【1】STM32的时钟系统 1.时钟基本概念 时钟源&#xff1a; 2.G030时钟源 3.时钟树 4.STM32CubeMX时钟树配置 【2】Systick定时器 1. 概念&#xff1a; 工作原理 时钟基准 【3】HAL_Delay函数分析 【4】定时器 基本概念 定时器分类 定时器组成 1.计数器 2.自…

软件测试----测试管理方法论

1、缺陷 &#xff08;1&#xff09;缺陷的主要变现&#xff1a; 1&#xff09;需求要求的功能没有实现 2&#xff09;实现了需求没有要求的功能 3&#xff09;软件中出现了明确指明不应该出现的错误 4&#xff09;需求虽未明确说明&#xff0c;但是应该实现的功能没有实现 5&…

MySQL高级|最强王者篇

&#x1f648;作者简介&#xff1a;练习时长两年半的Java up主 &#x1f649;个人主页&#xff1a;程序员老茶 &#x1f64a; ps:点赞&#x1f44d;是免费的&#xff0c;却可以让写博客的作者开兴好久好久&#x1f60e; &#x1f4da;系列专栏&#xff1a;Java全栈&#xff0c;…

【WSN覆盖】基于樽海鞘算法的三维无线传感器网络覆盖优化 三维WSN覆盖优化【Matlab代码#27】

文章目录 【可更换其他算法&#xff0c;获取资源请见文章第5节&#xff1a;资源获取】1. 原始樽海鞘算法2. 三维覆盖模型3. 部分代码展示4. 仿真结果展示5. 资源获取 【可更换其他算法&#xff0c;获取资源请见文章第5节&#xff1a;资源获取】 1. 原始樽海鞘算法 2. 三维覆盖模…

RHCE 第六次作业

1、判断当前磁盘剩余空间是否有20G&#xff0c;如果小于20G&#xff0c;则将报警邮件发送给管理员&#xff0c;每天检查一次磁盘剩余空间。 2、判断web服务是否运行&#xff08;1、查看进程的方式判断该程序是否运行&#xff0c;2、通过查看端口的方式判断该程序是否运行&…

【面试篇】SpringIoC、AOP、MVC面试实战

version&#xff1a;1.0 文章目录 SpringSpring基础 / IoC&#x1f64e;‍♂️面试官&#xff1a;举例Spring的模块&#xff1f;&#x1f64e;‍♂️面试官&#xff1a;Spring、SpringMVC、Spring Boot关系&#xff1f;&#x1f64e;‍♂️面试官&#xff1a;说说对SpringIoC的…

谈谈你对JavaSE中compare、compareTo的使用与比较

1. 前言 在java当中&#xff0c;若是要进行比较&#xff0c;大家可能第一时间想到&#xff0c; 或是 !&#xff0c;这种数学上的比较符>、接下来&#xff0c;我就分别介绍并演示这两种实现方法。 需要的朋友可以参考下&#xff0c;这将又会是干货满满的一期&#xff0c;全程…

【复习笔记】FreeRTOS(一)

FreeRTOS在校期间自学过一段时间&#xff0c;然而出来工作却用不上。 最近在搞东西需要用到RTOS&#xff0c;特意把笔记整理一下&#xff0c;算是复习了。笔记整理主要来源于正点原子的开发文档、视频教程。 文章目录 一、FreeRTOS简介二、FreeTROS移植三、测试例程四、实验效果…

docker搭建简单elk日志系统7(日志查看)

docker搭建简单elk日志系统1 docker搭建简单elk日志系统2 docker搭建简单elk日志系统3 docker搭建简单elk日志系统4 docker搭建简单elk日志系统5 docker搭建简单elk日志系统6 如有疑问可以去上面文档找相关内容 1.登录kibana 2. 以logs-test-dev为例 匹配到logs-test-dev数…

加拿大鹅Q4营收增长超30%,后续如何拿下更多“信任票”?

羽绒服行业正处在一个大混战的时代。有的品牌依托强势单品出海逆袭&#xff1b;有的品牌通过狂追当下Z世代的喜好&#xff0c;推翻经典设计&#xff1b;也有品牌“放下架子”在工厂忙起了特惠直播。在赛道愈发拥挤的背景下&#xff0c;羽绒服行业正在经历“地位”洗牌。 目前&…

如何高效地在网上找开源项目

开源项目是发展技能、分享想法和成为开发社区一员的好方法。开源意味着软件功能背后的源代码与所有想要阅读它的人公开共享。这意味着你可以准确地看到一个系统是如何工作的——一旦你愿意冒险&#xff0c;就为它做出贡献。除了向所有人开放贡献外&#xff0c;这种开放代码库通…