C++ Qt开发:运用QJSON模块解析数据

Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍如何运用QJson组件的实现对JSON文本的灵活解析功能。

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它易于人阅读和编写,也易于机器解析和生成。该格式是基于JavaScript语言的一个子集,但它是一种独立于语言的数据格式,因此可以在许多不同的编程语言中使用。

该数据是以键值对的形式组织的,其中键是字符串,值可以是字符串、数字、布尔值、数组、对象(即嵌套的键值对集合)或null,在Qt中默认提供了QJson系列类库,使用该类库可以很方便的解析和处理JSON文档。

1.1 解析单一键值对

实现解析根中的单一键值对,例如解析config.json配置文件中的blog,enable,status等这些独立的字段值,在解析之前需要先通过QJsonDocument::fromJson将内存中的字符串格式化为QJsonDocument类型,当有着该类型之后,则我们可以使用*.object()将其转换为对应的QJsonObject对象,在对象中我们可以调用各种方法对内存中的JSON数据进行处理。

以下是关于 QJsonDocument 类的一些常用方法的说明:

方法说明
QJsonDocument()构造函数,创建一个空的 JSON 文档。
QJsonDocument(const QJsonObject &object)通过给定的 JSON 对象构造 JSON 文档。
QJsonDocument(const QJsonArray &array)通过给定的 JSON 数组构造 JSON 文档。
QJsonDocument(const QJsonValue &value)通过给定的 JSON 值构造 JSON 文档。
QJsonDocument(const QJsonDocument &other)复制构造函数。
QJsonDocument &operator=(const QJsonDocument &other)赋值运算符。
bool isNull() const检查文档是否为空。
bool isEmpty() const检查文档是否为空,包括 JSON 数组或对象为空的情况。
QJsonObject object() const返回文档中的 JSON 对象。
QJsonArray array() const返回文档中的 JSON 数组。
QJsonValue value() const返回文档中的 JSON 值。
bool isArray() const检查文档是否包含 JSON 数组。
bool isObject() const检查文档是否包含 JSON 对象。
QByteArray toBinaryData() const将文档转换为二进制数据。
bool fromBinaryData(const QByteArray &data)从二进制数据恢复文档。
QString toJson(QJsonDocument::JsonFormat format = QJsonDocument::Compact) const返回 JSON 字符串表示,可以选择格式化的方式。
static QJsonDocument fromJson(const QString &json, QJsonParseError *error = nullptr)从 JSON 字符串创建文档。

以下是关于 QJsonObject 类的一些常用方法的说明:

方法说明
QJsonObject()构造函数,创建一个空的 JSON 对象。
QJsonObject(const QJsonObject &other)复制构造函数。
QJsonObject &operator=(const QJsonObject &other)赋值运算符。
bool isEmpty() const检查对象是否为空。
int size() const返回对象中键值对的数量。
bool contains(const QString &key) const检查对象中是否包含指定的键。
QStringList keys() const返回对象中所有键的列表。
QJsonValue value(const QString &key) const返回与指定键关联的值。
void insert(const QString &key, const QJsonValue &value)向对象中插入键值对。
QJsonObject &unite(const QJsonObject &other)将另一个对象的键值对合并到当前对象。
void remove(const QString &key)从对象中移除指定键及其关联的值。
QJsonValue take(const QString &key)移除并返回与指定键关联的值。
void clear()移除对象中的所有键值对,使其变为空对象。
QJsonDocument toDocument() const将对象转换为 JSON 文档。

当需要读取参数时只需要使用find()方法查询特定字段中的key值即可,按钮on_pushButton_clicked被点击后执行如下流程;

void MainWindow::on_pushButton_clicked()
{
    // 字符串格式化为JSON
    QJsonParseError err_rpt;
    QJsonDocument root_document = QJsonDocument::fromJson(config.toUtf8(), &err_rpt);
    if(err_rpt.error != QJsonParseError::NoError)
    {
        QMessageBox::information(nullptr,"提示","JSON格式错误",QMessageBox::Ok);
    }

    // 获取到Json字符串的根节点
    QJsonObject root_object = root_document.object();

    // 解析blog字段
    QString blog = root_object.find("blog").value().toString();
    //std::cout << "字段对应的值 = > "<< blog.toStdString() << std::endl;
    ui->lineEdit_blog->setText(blog);

    // 解析enable字段
    bool enable = root_object.find("enable").value().toBool();
    //std::cout << "是否开启状态: " << enable << std::endl;
    ui->lineEdit_enable->setText(QString::number(enable));

    // 解析status字段
    int status = root_object.find("status").value().toInt();
    //std::cout << "状态数值: " << status << std::endl;
    ui->lineEdit_status->setText(QString::number(status));
}

运行后点击读取数据按钮,输出效果如下;

1.2 解析单数组键值

实现解析简单的单一对象与单一数组结构,如配置文件中的GetDictGetList既是我们需要解析的内容,在解析时我们需要通过toVariantMap将字符串转换为对应的Map容器,当数据被转换后则就可以通过Map[]的方式很容易的将其提取出来。

void MainWindow::on_pushButton_2_clicked()
{
    // 字符串格式化为JSON
    QJsonParseError err_rpt;
    QJsonDocument  root_document = QJsonDocument::fromJson(config.toUtf8(), &err_rpt);
    if(err_rpt.error != QJsonParseError::NoError)
    {
        QMessageBox::information(nullptr,"提示","JSON格式错误",QMessageBox::Ok);
    }

    // 获取到Json字符串的根节点
    QJsonObject root_object = root_document.object();

    // 解析单一对象
    QJsonObject get_dict_ptr = root_object.find("GetDict").value().toObject();
    QVariantMap map = get_dict_ptr.toVariantMap();

    if(map.contains("address") && map.contains("username") && map.contains("password") && map.contains("update"))
    {
        QString address = map["address"].toString();
        QString username = map["username"].toString();
        QString password = map["password"].toString();
        QString update = map["update"].toString();

        std::cout
               << " 地址: " << address.toStdString()
               << " 用户名: " << username.toStdString()
               << " 密码: " << password.toStdString()
               << " 更新日期: " << update.toStdString()
               << std::endl;

        ui->listWidget->addItem(address);
        ui->listWidget->addItem(username);
        ui->listWidget->addItem(password);
        ui->listWidget->addItem(update);
    }

    // 解析单一数组
    QJsonArray get_list_ptr = root_object.find("GetList").value().toArray();

    for(int index=0; index < get_list_ptr.count(); index++)
    {
        int ref_value = get_list_ptr.at(index).toInt();
        std::cout << "输出数组元素: " << ref_value << std::endl;

        ui->listWidget_2->addItem(QString::number(ref_value));
    }
}

运行后点击解析数据按钮,输出效果如下;

1.3 解析多数组键值

实现解析字典嵌套字典或字典嵌套数组的结构,如配置文件中的ObjectInArrayJson则是一个字典中嵌套了另外两个字典而每个字典中的值又是一个Value数组,而与之相对应的ArrayJson则是在列表中嵌套了另外一个列表,这两中结构的使用读者可参照如下案例;

首先我们来看ObjectInArrayJson是如何被解析的,我们分别准备两个ComboBox选择框,当读者点击按钮时我们通过toVariantMap将字典转换为一个MAP容器,并通过toJsonArray转换内部的列表到JsonArray容器内,其初始化部分如下所示;

void MainWindow::on_pushButton_3_clicked()
{
    // 字符串格式化为JSON
    QJsonParseError err_rpt;
    QJsonDocument  root_document = QJsonDocument::fromJson(config.toUtf8(), &err_rpt);
    if(err_rpt.error != QJsonParseError::NoError)
    {
        QMessageBox::information(nullptr,"提示","JSON格式错误",QMessageBox::Ok);
    }

    // 获取到Json字符串的根节点
    QJsonObject root_object = root_document.object();

    // 找到Object对象
    QJsonObject one_object_json = root_object.find("ObjectInArrayJson").value().toObject();

    // 转为MAP映射
    QVariantMap map = one_object_json.toVariantMap();

    // 寻找One键
    QJsonArray array_one = map["One"].toJsonArray();

    for(int index=0; index < array_one.count(); index++)
    {
        QString value = array_one.at(index).toString();

        std::cout << "One => "<< value.toStdString() << std::endl;
        ui->comboBox->addItem(value);
    }

    // 寻找Two键
    QJsonArray array_two = map["Two"].toJsonArray();

    for(int index=0; index < array_two.count(); index++)
    {
        QString value = array_two.at(index).toString();

        std::cout << "Two => "<< value.toStdString() << std::endl;
        ui->comboBox_2->addItem(value);
    }
}

同理,要实现解析数组中的数组也可以通过该方式实现,如配置文件中的ArrayJson既是我们需要解析的内容,首先我们通过isArray判断该节点是否为数组,如果是则通过toArray().at方法以此得到不同下标元素参数,并依次循环即可,其代码如下所示;

void MainWindow::on_pushButton_4_clicked()
{
    // 字符串格式化为JSON
    QJsonParseError err_rpt;
    QJsonDocument  root_document = QJsonDocument::fromJson(config.toUtf8(), &err_rpt);
    if(err_rpt.error != QJsonParseError::NoError)
    {
        QMessageBox::information(nullptr,"提示","JSON格式错误",QMessageBox::Ok);
    }

    // 获取到Json字符串的根节点
    QJsonObject root_object = root_document.object();

    // 获取MyJson数组
    QJsonValue array_value = root_object.value("ArrayJson");

    // 验证节点是否为数组
    if(array_value.isArray())
    {
        // 得到数组个数
        int array_count = array_value.toArray().count();

        // 循环数组个数
        for(int index=0;index <= array_count;index++)
        {
            QJsonValue parset = array_value.toArray().at((index));
            if(parset.isArray())
            {
                QString address = parset.toArray().at(0).toString();
                QString username = parset.toArray().at(1).toString();
                QString userport = parset.toArray().at(2).toString();

                std::cout
                        << "地址: " << address.toStdString()
                        << "用户名: " << username.toStdString()
                        << "端口号: " << userport.toStdString()
                << std::endl;

                ui->comboBox_3->addItem(address);
                ui->comboBox_4->addItem(username);
                ui->comboBox_5->addItem(userport);
            }
        }
    }
}

运行后点击两个初始化按钮则可以将字典或列表中的数据依次解析到不同的ComBobox列表框内,输出效果如下;

1.4 解析多字典键值

实现解析字典中嵌套多个参数或字典中嵌套参数中包含列表的数据集,如配置文件中的ObjectJson则是字典中存在多个键值对,而ObjectArrayJson则更进一步在多键值对中增加了列表的支持,解析此类内容只需要依次逐级拆分即可,我们来看下如何实现对这些键值的灵活提取;

首先我们来实现对ObjectJson的参数解析功能,读者可自行对比与之前1.3中的区别,可以发现这两者的差别其实不大,解析ObjectJson完整代码如下所示;

void MainWindow::on_pushButton_5_clicked()
{
    // 字符串格式化为JSON
    QJsonParseError err_rpt;
    QJsonDocument  root_document = QJsonDocument::fromJson(config.toUtf8(), &err_rpt);
    if(err_rpt.error != QJsonParseError::NoError)
    {
        QMessageBox::information(nullptr,"提示","JSON格式错误",QMessageBox::Ok);
    }

    // 获取到Json字符串的根节点
    QJsonObject root_object = root_document.object();

    // 获取MyJson数组
    QJsonValue object_value = root_object.value("ObjectJson");

    // 验证是否为数组
    if(object_value.isArray())
    {
        // 获取对象个数
        int object_count = object_value.toArray().count();

        // 循环个数
        for(int index=0;index <= object_count;index++)
        {
            QJsonObject obj = object_value.toArray().at(index).toObject();

            // 验证数组不为空
            if(!obj.isEmpty())
            {
                QString address = obj.value("address").toString();
                QString username = obj.value("username").toString();

                std::cout << "地址: " << address.toStdString() << " 用户: " << username.toStdString() << std::endl;
                ui->comboBox_6->addItem(address);
                ui->comboBox_7->addItem(username);
            }
        }
    }
}

接着我们来实现一个更为复杂的需求,解析多字典中嵌套的数组,如配置文件中的ObjectArrayJson则是我们需要解析的内容,在之前解析字典部分保持与上述案例一致,唯一不同的是我们需要通过value("ulist").toArray()获取到对应字典中的数组,并通过循环的方式输出。

如下案例中,当读者点击初始化按钮时我们首先让字典中的数据填充之ComboBox列表框中,接着当读者点击第一个列表框时我们让其过滤出特定的内容并赋值到第二个列表框中,以此实现联动效果,首先初始化部分如下所示;

void MainWindow::on_pushButton_6_clicked()
{
    // 字符串格式化为JSON
    QJsonParseError err_rpt;
    QJsonDocument  root_document = QJsonDocument::fromJson(config.toUtf8(), &err_rpt);
    if(err_rpt.error != QJsonParseError::NoError)
    {
        QMessageBox::information(nullptr,"提示","JSON格式错误",QMessageBox::Ok);
    }

    // 获取到Json字符串的根节点
    QJsonObject root_object = root_document.object();

    // 获取MyJson数组
    QJsonValue object_value = root_object.value("ObjectArrayJson");

    // 验证是否为数组
    if(object_value.isArray())
    {
        // 获取对象个数
        int object_count = object_value.toArray().count();

        // 循环个数
        for(int index=0;index <= object_count;index++)
        {
            QJsonObject obj = object_value.toArray().at(index).toObject();

            // 验证数组不为空
            if(!obj.isEmpty())
            {
                QString uname = obj.value("uname").toString();
                std::cout << "用户名: " << uname.toStdString() <<  std::endl;

                ui->comboBox_8->addItem(uname);

                // 解析该用户的数组
                int array_count = obj.value("ulist").toArray().count();

                std::cout << "数组个数: "<< array_count << std::endl;

                for(int index=0;index < array_count;index++)
                {
                    QJsonValue parset = obj.value("ulist").toArray().at(index);

                    int val = parset.toInt();

                    std::cout << "Value = > "<< val << std::endl;
                    ui->comboBox_9->addItem(QString::number(val));
                }
            }
        }
    }
}

当第一个选择框被选中时我们触发currentIndexChanged信号,在其中只需要判断uname.compare(arg1)是否相等如果相等则addItem追加到新的列表内,运行效果如下所示,详细实现可参考附件。

1.5 解析多字典嵌套

实现解析多个字典嵌套或多个列表嵌套的结构,如配置文件中的NestingObjectJson则是字典中嵌套字典,而ArrayNestingArrayJson则是列表中嵌套列表,两种的解析方式基本一致。

我们首先来实现第一种格式的解析,当按钮被点击后,我们首先查询uuid字段并赋值到ComBobox列表中,实现代码如下所示;

void MainWindow::on_pushButton_7_clicked()
{
    // 字符串格式化为JSON
    QJsonParseError err_rpt;
    QJsonDocument  root_document = QJsonDocument::fromJson(config.toUtf8(), &err_rpt);
    if(err_rpt.error != QJsonParseError::NoError)
    {
        QMessageBox::information(nullptr,"提示","JSON格式错误",QMessageBox::Ok);
    }

    // 获取到Json字符串的根节点
    QJsonObject root_object = root_document.object();

    // 获取NestingObjectJson数组
    QJsonValue array_value = root_object.value("NestingObjectJson");

    // 验证节点是否为数组
    if(array_value.isArray())
    {
        // 得到内部对象个数
        int count = array_value.toArray().count();
        std::cout << "对象个数: " << count << std::endl;

        for(int index=0; index < count; index++)
        {
            // 得到数组中的index下标中的对象
            QJsonObject array_object = array_value.toArray().at(index).toObject();

            QString uuid = array_object.value("uuid").toString();

            // 追加数据
            std::cout << uuid.toStdString() << std::endl;
            ui->comboBox_10->addItem(uuid);

            // 开始解析basic中的数据
            QJsonObject basic = array_object.value("basic").toObject();

            QString lat = basic.value("lat").toString();
            QString lon = basic.value("lon").toString();

            std::cout << "解析basic中的lat字段: " << lat.toStdString() << std::endl;
            std::cout << "解析basic中的lon字段: " << lon.toStdString()<< std::endl;

            // 解析单独字段
            QString status = array_object.value("status").toString();
            std::cout << "解析字段状态: " << status.toStdString() << std::endl;
        }
    }
}

ComBobox组件中的currentIndexChanged信号被触发时,则直接执行对LineEdit编辑框的赋值操作,其代码如下所示;

void MainWindow::on_comboBox_10_currentIndexChanged(const QString &arg1)
{
    // 字符串格式化为JSON
    QJsonParseError err_rpt;
    QJsonDocument  root_document = QJsonDocument::fromJson(config.toUtf8(), &err_rpt);
    if(err_rpt.error != QJsonParseError::NoError)
    {
        QMessageBox::information(nullptr,"提示","JSON格式错误",QMessageBox::Ok);
    }

    // 获取到Json字符串的根节点
    QJsonObject root_object = root_document.object();

    // 获取NestingObjectJson数组
    QJsonValue array_value = root_object.value("NestingObjectJson");

    // 验证节点是否为数组
    if(array_value.isArray())
    {
        // 得到内部对象个数
        int count = array_value.toArray().count();
        std::cout << "对象个数: " << count << std::endl;

        for(int index=0; index < count; index++)
        {
            // 得到数组中的index下标中的对象
            QJsonObject array_object = array_value.toArray().at(index).toObject();

            QString uuid = array_object.value("uuid").toString();

            // 对比是否相等
            if(uuid.compare(arg1) == 0)
            {
                // 开始解析basic中的数据
                QJsonObject basic = array_object.value("basic").toObject();

                QString lat = basic.value("lat").toString();
                QString lon = basic.value("lon").toString();

                std::cout << "解析basic中的lat字段: " << lat.toStdString() << std::endl;
                std::cout << "解析basic中的lon字段: " << lon.toStdString()<< std::endl;

                ui->lineEdit->setText(lat);
                ui->lineEdit_2->setText(lon);

                // 解析单独字段
                QString status = array_object.value("status").toString();
                std::cout << "解析字段状态: " << status.toStdString() << std::endl;
            }
        }
    }
}

同理,我们也可以实现字典中嵌套列表结构,如配置文件中的ArrayNestingArrayJson既我们需要解析的内容,解析实现方法与上述代码保持一致,首先当按钮被点击后我们直接对ComBobox组件进行初始化,代码如下所示;

void MainWindow::on_pushButton_8_clicked()
{
    // 字符串格式化为JSON
    QJsonParseError err_rpt;
    QJsonDocument  root_document = QJsonDocument::fromJson(config.toUtf8(), &err_rpt);
    if(err_rpt.error != QJsonParseError::NoError)
    {
        std::cout << "json 格式错误" << std::endl;
    }

    // 获取到Json字符串的根节点
    QJsonObject root_object = root_document.object();

    // 获取NestingObjectJson数组
    QJsonValue array_value = root_object.value("ArrayNestingArrayJson");

    // 验证节点是否为数组
    if(array_value.isArray())
    {
        // 得到数组中的0号下标中的对象
        QJsonObject array_object = array_value.toArray().at(0).toObject();

        // 解析手机号字符串
        QString telephone = array_object.value("telephone").toString();
        std::cout << "手机号: " << telephone.toStdString() << std::endl;

        ui->comboBox_11->addItem(telephone);

        // 定位外层数组
        QJsonArray root_array = array_object.find("path").value().toArray();
        std::cout << "外层循环计数: " << root_array.count() << std::endl;

        for(int index=0; index < root_array.count(); index++)
        {
            // 定位内层数组
            QJsonArray sub_array = root_array.at(index).toArray();
            std::cout << "内层循环计数: "<< sub_array.count() << std::endl;

            for(int sub_count=0; sub_count < sub_array.count(); sub_count++)
            {
                // 每次取出最里层数组元素
                float var = sub_array.toVariantList().at(sub_count).toFloat();

                std::cout << "输出元素: " << var << std::endl;
                // std::cout << sub_array.toVariantList().at(0).toFloat() << std::endl;

                ui->listWidget_3->addItem(QString::number(var));
            }
        }
    }
}

运行效果如下图所示;

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

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

相关文章

【python】求矩阵的特征值和特征向量

使用np.linalg.eig同时求特征值和特征向量 import numpy as np#输入矩阵 A np.array([[1, 1/2, 1/6, 1/9],[2, 1, 1/3, 1/5],[6, 3,1,1/2],[9, 5,2,1]])#求解特征值和其对应的特征向量 eigval,eigvec np.linalg.eig(A) for i in range(len(eigval)):print(f特征值&#xff1a…

Flask使用Jinja2渲染模版使用变量实战

前言&#xff1a; Flask 使用 Jinja2 作为其默认模板引擎&#xff0c;这意味着您可以直接在 Flask 应用程序中使用 Jinja2 模板。您可以创建模板文件&#xff0c;然后在视图函数中渲染这些模板&#xff0c;将动态数据传递给模板进行渲染&#xff0c;并最终生成最终的 HTML 页面…

349. 两个数组的交集(力扣LeetCode)

文章目录 349. 两个数组的交集题目描述数组解题set容器解题该思路数组版解题 349. 两个数组的交集 题目描述 给定两个数组 nums1 和 nums2 &#xff0c;返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 示例 1&#xff1a; 输入&a…

MATLAB知识点:创建MATLAB的脚本

​讲解视频&#xff1a;可以在bilibili搜索《MATLAB教程新手入门篇——数学建模清风主讲》。​ MATLAB教程新手入门篇&#xff08;数学建模清风主讲&#xff0c;适合零基础同学观看&#xff09;_哔哩哔哩_bilibili 节选自第2章 在实际应用中&#xff0c;直接在命令行窗口中输…

Phoncent博客,探索Rie Kudan的GPT创作之举

近日&#xff0c;大家都在谈论日本作家Rie Kudan&#xff0c;她凭借其小说《东京共鸣塔》&#xff08;"Tokyo-to Dojo-to"&#xff09;荣获了日本极具声望的芥川奖。这本小说引起了广泛的讨论和思考&#xff0c;因为令人惊讶的是&#xff0c;Kudan在其中直接引用了人…

伊恩·斯图尔特《改变世界的17个方程》毕达哥拉斯定理笔记

它告诉我们什么&#xff1f; 直角三角形的三个边之间有什么关系。 为什么重要&#xff1f; 它提供了几何和代数之间的重要联系&#xff0c;使我们能够根据坐标计算距离。它也催生出了三角学。 它带来了什么&#xff1f; 测绘、导航&#xff0c;以及较近代出现的狭义和广义相对论…

solr的原理是什么

1 Java程序里如果有无限for循环的代码导致CPU负载超高&#xff0c;如何排查&#xff1f; 排查Java程序中由于无限循环导致的CPU负载过高的问题&#xff0c;可以按照以下步骤进行&#xff1a; 资源监控&#xff1a; 使用系统命令行工具&#xff08;如Linux上的top或htop&#xf…

Pytest 识别case规则

一、Python测试框架&#xff0c;主要特点有以下几点&#xff1a; 简单灵活&#xff0c;容易上手&#xff1b;支持参数化&#xff1b;能够支持简单的单元测试和复杂的功能测试&#xff0c;还可以用来做selenium/appnium等自动化测试、接口自动化测试&#xff08;pytestrequests…

JavaWeb中的Filter(过滤器)和 Listener(监听器)

提示&#xff1a;这两个东西听起来似乎很难&#xff0c;实际上是非常简单的&#xff0c;按照要求写就行了&#xff0c;一定不要被新名词给吓到了。 JavaWeb中的Filter&#xff08;过滤器&#xff09; 一、Filter&#xff08;过滤器&#xff09;1.如何编写 Filter2.Filter 中的细…

翻译: GPT-4 Vision征服LLM幻觉hallucinations 升级Streamlit六

GPT-4 Vision 系列: 翻译: GPT-4 with Vision 升级 Streamlit 应用程序的 7 种方式一翻译: GPT-4 with Vision 升级 Streamlit 应用程序的 7 种方式二翻译: GPT-4 Vision静态图表转换为动态数据可视化 升级Streamlit 三翻译: GPT-4 Vision从图像转换为完全可编辑的表格 升级St…

探索Pyecharts:绘制多彩日历图的艺术与技巧

Pyecharts绘制多种炫酷日历图参数说明代码实战 导言 在数据可视化领域&#xff0c;日历图是一种直观展示时间和数据关系的方式。Pyecharts是一个基于Echarts的Python库&#xff0c;可以方便地绘制各种图表&#xff0c;包括炫酷的日历图。本篇博客将介绍Pyecharts中绘制多种炫…

Maya---补洞 桥接 连接

14.maya常用命令4.补洞 桥接 连接_哔哩哔哩_bilibili 边模式下&#xff1a; shift右键--->填充洞 对象模式下&#xff0c;可一次填充多个洞 桥接 连接工具 ctrlshift右键

SNP干货分享:SAP数据脱敏的具体实施步骤

随着信息技术的飞速发展&#xff0c;大数据时代的到来使得数据成为国家经济、企业竞争力和个人隐私的重要载体。在这种背景下&#xff0c;数据安全问题日益凸显&#xff0c;各国政府纷纷出台相关法规以保护数据安全。我国也不断完善数据安全法规体系&#xff0c;以确保国家利益…

HCIA-Datacom实验指导手册:4.1 实验一:访问控制列表配置实验,fragment分片acl演示。

HCIA-Datacom实验指导手册:4.1 实验一:访问控制列表配置实验 一、实验介绍:二、实验拓扑:三、实验目的:四、配置步骤:步骤 1 掌握ACL的配置方法 配置方法步骤 2 掌握 ACL在接口下应用方法步骤 3 掌握 流量过滤 的基本方式步骤 4 掌握 禁止分片报文通过的方法验证五、结果…

Git怎样用?(下载到本地,和在本地初始化)

全局设置&#xff1a; 点击第二个 输入&#xff1a; 例如&#xff1b;邮箱是随意地 git config --global user.name "名字" git config --global user.email "邮箱" 获取git仓库 本地初始化&#xff1a; 创建仓库 右键第二个 输入 git init 克隆&#…

Redis(九)集群(cluster)

文章目录 概述作用1. redis集群的槽位slot2. redis集群的分片3. 第1,2点的优势&#xff1a;**最大优势&#xff0c;方便扩缩容和数据分派查找**4. slot槽位映射&#xff0c;一般业界有3种解决方案第一种&#xff1a;哈希取余分区第二种&#xff1a;一致性哈希算法分区第三种&am…

U-Boot学习(6):初始化之_main函数源码分析

在上一节系统初始化之start.S源码分析详解中&#xff0c;我们分析了上电后的代码执行流程&#xff0c;实际上就是对系统特权模式、CP15、向量表等进行配置。最后一步就是进入_main函数了&#xff0c;这个就是U-Boot的主程序了&#xff0c;它完成了对系统内存、堆栈、全局结构体…

TensorFlow2实战-系列教程7:TFRecords数据源制作1

&#x1f9e1;&#x1f49b;&#x1f49a;TensorFlow2实战-系列教程 总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Jupyter Notebook中进行 本篇文章配套的代码资源已经上传 1、TFRecords 在训练过程中&#xff0c;基本都是使用GPU来计算&#xff0c;但是取一个…

防火墙知识普及详解,使用TOR Router把TOR作为默认网关,增加隐私/匿名性

防火墙知识普及详解,使用TOR Router把TOR作为默认网关,增加隐私/匿名性。 #################### 免责声明:工具本身并无好坏,希望大家以遵守《网络安全法》相关法律为前提来使用该工具,支持研究学习,切勿用于非法犯罪活动,对于恶意使用该工具造成的损失,和本人及开发者…

【ArcGIS微课1000例】0099:土地利用变化分析

本实验讲述在ArcGIS软件中基于两期土地利用数据,做土地利用变化分析。 文章目录 一、实验描述二、实验过程三、注意事项一、实验描述 对城市土地利用情况进行分析时,需要考虑不同时期土地利用图层在空间上的差异性,如农用地转建筑用地的空间变化。而该变化过程表现为各时期…