qt笔记之qml和C++的交互系列(二):rootObject

qt笔记之qml和C++的交互系列(二):rootObject

code review!

—— 2024-06-17 杭州 夜

文章目录

  • qt笔记之qml和C++的交互系列(二):rootObject
    • 一.使用rootObject例程
      • 1.运行
      • 2.main.cpp
      • 3.main.qml
      • 3.用于Debug的加长版main.cpp
    • 二.QML文件的根对象详解
      • 基本概念
      • 常见根对象类型
        • Rectangle
        • ApplicationWindow
      • 属性和方法
      • 作用域和继承
    • 三.使用`rootObject`通过`QObject`的`setProperty`方法,可以设置`QML对象的属性`。`rootObjects`和 `QMetaObject::invokeMethod`的结合使用调用`QML中的方法`
      • 3.1.运行
      • 3.2.main.cpp
      • 3.3.main.qml
    • 四.理解`rootObjects`和`QMetaObject::invokeMethod`的结合使用
      • 理解 `rootObjects` 和 `QMetaObject::invokeMethod` 的结合使用
      • 详细示例
        • 1. 加载 QML 文件并获取根对象
        • 2. 动态调用 QML 方法
      • 为什么 `QMetaObject::invokeMethod` 不能单独使用?
      • 总结
    • 五.`rootObjects`是一个`QObject列表`,包含了通过该引擎加载的QML文档的根对象
      • 作用
      • 示例代码
    • 六.为什么findChild<QObject*>("myRectangle") 不起作用:`id` vs `objectName`
      • `id` vs. `objectName`
      • 为什么 `findChild<QObject*>("myRectangle")` 不起作用
      • 为什么 `objectName` 有效
      • 如何仅使用 `findChild<QObject*>("myRectangle")`
        • 示例
          • QML 文件:`main.qml`
          • C++ 文件:`main.cpp`
      • 总结

一.使用rootObject例程

1.运行

在这里插入图片描述

2.main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QQmlComponent>
#include <QDebug>

int main(int argc, char *argv[]) {
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    if (engine.rootObjects().isEmpty()) {
        qDebug() << "No root objects found.";
        return -1;
    }

    QObject *rootObject = engine.rootObjects().first();
    QObject *rectangle = rootObject->findChild<QObject*>("myRectangle", Qt::FindChildrenRecursively);

    if (rectangle) {
        // 修改属性
        rectangle->setProperty("width", 200);
        // 调用方法
        QVariant newColor = "blue";
        QMetaObject::invokeMethod(rectangle, "changeColor", Q_ARG(QVariant, newColor));
    } else {
        qDebug() << "Rectangle object not found.";
        return -1;
    }

    return app.exec();
}

3.main.qml

import QtQuick 2.0
import QtQuick.Controls 2.5

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: "Hello World"

    Rectangle {
        id: myRectangle
        objectName: "myRectangle"  // 添加 objectName
        width: 100
        height: 100
        color: "red"

        function changeColor(newColor) {
            console.log("Changing color to: " + newColor)
            color = newColor;
        }
    }
}

3.用于Debug的加长版main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QQmlComponent>
#include <QDebug>

void printObjectTree(QObject *object, int level = 0) {
    if (!object) return;
    QString indent(level * 2, ' ');
    qDebug() << indent << object->objectName() << "(" << object->metaObject()->className() << ")";
    const QObjectList children = object->children();
    for (QObject *child : children) {
        printObjectTree(child, level + 1);
    }
}

int main(int argc, char *argv[]) {
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    if (engine.rootObjects().isEmpty()) {
        qDebug() << "No root objects found.";
        return -1;
    }

    QObject *rootObject = engine.rootObjects().first();
    if (!rootObject) {
        qDebug() << "Root object not found.";
        return -1;
    }

    qDebug() << "Root object found. Printing object tree:";
    printObjectTree(rootObject);

    QObject *rectangle = rootObject->findChild<QObject*>("myRectangle", Qt::FindChildrenRecursively);
    if (!rectangle) {
        qDebug() << "Rectangle object not found.";
        return -1;
    } else {
        qDebug() << "Rectangle object found.";
    }

    // 修改属性
    if (rectangle->setProperty("width", 200)) {
        qDebug() << "Width changed successfully.";
    } else {
        qDebug() << "Failed to change width.";
    }

    // 调用方法
    QVariant newColor = "blue";
    if (QMetaObject::invokeMethod(rectangle, "changeColor", Q_ARG(QVariant, newColor))) {
        qDebug() << "changeColor method called successfully.";
    } else {
        qDebug() << "Failed to call changeColor method.";
    }

    return app.exec();
}

运行打印

Root object found. Printing object tree:
"" "" ( ApplicationWindow_QMLTYPE_0 )
"  " "" ( QQuickRootItem )
"    " "" ( QQuickOverlay )
"      " "" ( QQmlComponent )
"      " "" ( QQmlComponent )
"    " "ApplicationWindow" ( QQuickContentItem )
"  " "myRectangle" ( QQuickRectangle_QML_3 )
Rectangle object found.
Width changed successfully.
qml: Changing color to: blue
changeColor method called successfully.

二.QML文件的根对象详解

在 QML(Qt Meta Language)中,QML 文件的根对象是整个用户界面组件的基础。根对象定义了该文件中所有子对象的上下文和作用域。通常,根对象是一个 UI 组件,比如 RectangleItemApplicationWindow 等,以下是对 QML 文件根对象的详解:

基本概念

  1. 唯一性

    • 每个 QML 文件必须且只能有一个根对象。这是 QML 文件的入口点,所有其他元素都必须嵌套在这个根对象之内。
  2. 类型选择

    • 根对象可以是任何 QML 类型,但通常会选择合适的 UI 组件,根据需要创建不同类型的根对象。例如,可以使用 Rectangle 创建一个矩形区域,或者使用 ApplicationWindow 创建一个完整的应用窗口。
  3. 作用域

    • 根对象定义了一个新的作用域,文件内的所有子对象都在这个作用域内。这意味着根对象的属性和方法可以被子对象访问和修改。

常见根对象类型

Rectangle
Rectangle {
    width: 200
    height: 200
    color: "lightblue"

    Text {
        text: "Hello, QML!"
        anchors.centerIn: parent
    }
}
  • Rectangle 是一个常见的根对象类型,用于定义一个矩形区域。
ApplicationWindow
import QtQuick 2.15
import QtQuick.Controls 2.15

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: "QML Application"

    Button {
        text: "Click Me"
        anchors.centerIn: parent
    }
}
  • ApplicationWindow 用于创建一个完整的应用窗口,通常用于更复杂的应用程序。

属性和方法

根对象可以包含属性和方法,这些属性和方法可以在子对象中访问。例如:

Rectangle {
    id: root
    width: 300
    height: 300
    color: "lightgreen"

    function changeColor(newColor) {
        root.color = newColor
    }

    MouseArea {
        anchors.fill: parent
        onClicked: root.changeColor("lightcoral")
    }
}

作用域和继承

根对象中的属性和方法可以被子对象继承和使用。例如:

Rectangle {
    id: root
    width: 400
    height: 400
    color: "lightyellow"

    property string message: "Hello from root"

    Text {
        text: root.message
        anchors.centerIn: parent
    }
}

三.使用rootObject通过QObjectsetProperty方法,可以设置QML对象的属性rootObjectsQMetaObject::invokeMethod的结合使用调用QML中的方法

3.1.运行

在这里插入图片描述

3.2.main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QQuickItem>
#include <QMetaObject>

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    if (engine.rootObjects().isEmpty())
        return -1;

    QObject *rootObject = engine.rootObjects().first();
    QObject *rectangle = rootObject->findChild<QObject*>("myRectangle");

    if (rectangle) {
        qDebug() << "Rectangle found!";
        rectangle->setProperty("width", 300);
        rectangle->setProperty("color", "red");
        QMetaObject::invokeMethod(rectangle, "changeColor", Q_ARG(QVariant, "green"));
    } else {
        qDebug() << "Rectangle not found!";
    }

    return app.exec();
}

3.3.main.qml

import QtQuick 2.0
import QtQuick.Controls 2.5

ApplicationWindow {
    visible: true
    width: 640
    height: 480

    Rectangle {
        id: myRectangle
        objectName: "myRectangle"  // 添加 objectName
        width: 200
        height: 200
        color: "blue"

        function changeColor(newColor) {
            color = newColor;
        }
    }
}

四.理解rootObjectsQMetaObject::invokeMethod的结合使用

rootObjectsQMetaObject::invokeMethod 可以结合使用,特别是在需要从 C++ 调用 QML 中的方法时。让我们详细解释一下这个过程,并澄清为什么 QMetaObject::invokeMethod 不能单独用于调用 QML 中的方法。

理解 rootObjectsQMetaObject::invokeMethod 的结合使用

  1. 获取 QML 根对象:

    • 使用 rootObjects 获取 QML 加载后的根对象。这一步是必要的,因为需要一个具体的 QML 对象实例来调用其方法。
  2. 使用 QMetaObject::invokeMethod 调用 QML 方法:

    • 一旦有了 QML 的根对象(或任何需要调用方法的对象),可以使用 QMetaObject::invokeMethod 动态调用其方法。

详细示例

假设有一个简单的 QML 文件 main.qml,其中定义了一个方法 myQmlMethod

import QtQuick 2.0

Rectangle {
    width: 200
    height: 200

    function myQmlMethod() {
        console.log("myQmlMethod called")
    }
}

在 C++ 中,可以按以下步骤调用这个方法:

1. 加载 QML 文件并获取根对象
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QObject>
#include <QMetaObject>

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    if (engine.rootObjects().isEmpty())
        return -1;

    QObject *rootObject = engine.rootObjects().first();

    // Now use QMetaObject::invokeMethod to call the QML method
    QMetaObject::invokeMethod(rootObject, "myQmlMethod");

    return app.exec();
}
2. 动态调用 QML 方法
// Assuming rootObject is already obtained as shown above
QMetaObject::invokeMethod(rootObject, "myQmlMethod");

为什么 QMetaObject::invokeMethod 不能单独使用?

QMetaObject::invokeMethod 需要一个具体的对象实例以及方法名称来调用方法。它不直接与 QML 交互,而是用于调用任何 QObject 派生类的实例方法。因此,必须首先通过 rootObjects 获取 QML 加载后的对象实例,然后才能使用 QMetaObject::invokeMethod 调用该对象的方法。

总结

  • rootObjects: 用于获取 QML 加载后的根对象。
  • QMetaObject::invokeMethod: 用于动态调用 QObject 实例的方法。

这两者结合使用时,首先通过 rootObjects 获取 QML 对象实例,然后使用 QMetaObject::invokeMethod 调用该对象的方法。这样可以在 C++ 代码中灵活地调用 QML 中定义的方法。

五.rootObjects是一个QObject列表,包含了通过该引擎加载的QML文档的根对象

属性/方法描述
rootObjects返回一个包含所有通过该引擎加载的 QML 根对象的列表。
append()添加一个对象到 rootObjects 列表。
at(int index)返回 rootObjects 列表中指定索引处的对象。
clear()清空 rootObjects 列表。
contains(QObject* obj)检查 rootObjects 列表是否包含指定的对象。
indexOf(QObject* obj)返回指定对象在 rootObjects 列表中的索引,如果不包含返回 -1。
removeAt(int index)移除 rootObjects 列表中指定索引处的对象。
size()返回 rootObjects 列表的大小。
first()返回 rootObjects 列表中的第一个对象。
last()返回 rootObjects 列表中的最后一个对象。

作用

  1. 访问根对象: 可以方便地访问通过 QML 加载的主界面对象,通常用于设置属性或调用方法。
  2. 对象管理: 允许在运行时动态地管理 QML 根对象,例如添加、移除或替换根对象。
  3. 调试和测试: 在调试和测试过程中,可以通过 rootObjects 访问和操作 QML 对象树进行检查和验证。

示例代码

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QDebug>

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    if (engine.rootObjects().isEmpty())
        return -1;

    // 获取第一个根对象
    QObject *rootObject = engine.rootObjects().first();
    qDebug() << "Root object:" << rootObject;

    return app.exec();
}

在这个示例中,engine.rootObjects().first() 获取并打印了加载的 QML 文档的根对象。

六.为什么findChild<QObject*>(“myRectangle”) 不起作用:id vs objectName

在 Qt 中,findChild 方法用于查找对象树中的子对象。默认情况下,它只会查找直接的子对象,而不会递归地查找整个对象树。此外,findChild 方法通常依赖于对象的 objectName 属性,而不是 id 属性。

id vs. objectName

  • id:在 QML 中,id 是一个局部标识符,用于在 QML 文件中引用对象。它在 C++ 层不可见。
  • objectName:这是一个标准的 Qt 属性,可用于在 C++ 和 QML 层之间进行对象查找和引用。

为什么 findChild<QObject*>("myRectangle") 不起作用

提到的代码:

QObject *rectangle = rootObject->findChild<QObject*>("myRectangle");

如果没有设置 objectName,这个方法不会成功,因为它只查找对象的 objectName 属性,而不是 id

为什么 objectName 有效

当将 objectName 设置为 "myRectangle" 时,findChild 方法可以成功找到对象:

Rectangle {
    id: myRectangle
    objectName: "myRectangle"  // 添加 objectName
    ...
}

在 C++ 中:

QObject *rectangle = rootObject->findChild<QObject*>("myRectangle", Qt::FindChildrenRecursively);

使用 Qt::FindChildrenRecursively 标志可以确保在对象树中递归查找。

如何仅使用 findChild<QObject*>("myRectangle")

如果希望不使用递归查找,且对象位于 rootObject 的直接子对象中,需要确保对象的 objectName 已正确设置,并且对象确实是 rootObject 的直接子对象。

示例
QML 文件:main.qml
import QtQuick 2.0
import QtQuick.Controls 2.5

ApplicationWindow {
    visible: true
    width: 640
    height: 480

    Rectangle {
        id: myRectangle
        objectName: "myRectangle"  // 添加 objectName
        width: 200
        height: 200
        color: "blue"

        function changeColor(newColor) {
            color = newColor;
        }
    }
}
C++ 文件:main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QQuickItem>
#include <QMetaObject>

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    if (engine.rootObjects().isEmpty())
        return -1;

    QObject *rootObject = engine.rootObjects().first();
    QObject *rectangle = rootObject->findChild<QObject*>("myRectangle");

    if (rectangle) {
        qDebug() << "Rectangle found!";
        rectangle->setProperty("width", 300);
        rectangle->setProperty("color", "red");
        QMetaObject::invokeMethod(rectangle, "changeColor", Q_ARG(QVariant, "green"));
    } else {
        qDebug() << "Rectangle not found!";
    }

    return app.exec();
}

总结

为了在 C++ 代码中成功找到 QML 对象,需要确保以下几点:

  1. 在 QML 中设置对象的 objectName 属性。
  2. 使用 findChild 方法进行对象查找时,查找的是 objectName,而不是 id
  3. 如果对象不是直接子对象,使用 Qt::FindChildrenRecursively 标志进行递归查找。

这样做可以确保能够在 C++ 代码中准确查找到所需的 QML 对象。

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

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

相关文章

【减法网络】Minusformer:通过逐步学习残差来改进时间序列预测

摘要 本文发现泛在时间序列(TS)预测模型容易出现严重的过拟合。为了解决这个问题&#xff0c;我们采用了一种去冗余的方法来逐步恢复TS的真实值。具体来说&#xff0c;我们引入了一种双流和减法机制&#xff0c;这是一种深度Boosting集成学习方法。通过将信息聚合机制从加法转…

【最全面最优质的PyTorch学习资源】

纯 PyTorch 资源 PyTorch 博客 https://pytorch.org/blog/ PyTorch 文档 https://pytorch.org/docs PyTorch 性能调优指南 https://pytorch.org/tutorials/recipes/recipes/tuning_guide.html# PyTorch Recipes https://pytorch.org/tutorials/recipes/recipes_index.h…

AI 有感:智能体 = 提示词工程 + 大模型算力 + 插件类工具?

回顾 继这篇文章推出&#xff1a;怎么看 AI 大模型&#xff08;LLM&#xff09;、智能体&#xff08;Agent&#xff09;、知识库、向量数据库、知识图谱&#xff0c;RAG&#xff0c;AGI 的不同形态&#xff1f; 引起了很多粉丝朋友的反响&#xff0c;随着目前各大模型的发布以…

PBC密码库安装及使用教程

文章目录 1.PBC库介绍2.PBC库安装3.PBC库使用4.相关API4.1 配对的初始化和释放4.2 元素的初始化和释放4.3 元素的赋值4.4 哈希4.5 元素的常用运算4.6 元素的幂运算4.7 元素的比较4.8 从群中随机选取一个元素&#xff08;常用&#xff09;4.9 配对的运算4.10 小结 5.Some exampl…

Unity 使用TextMeshPro实现图文混排

最后实现出的效果是这样的 开始实现 准备两张图 选中图片右键->Create->TextMeshPro->Sprite Asset 然后文件夹内就会出现一个同名的这个文件 新建一个Text Inspector面板 点击最底下的Extra Settings 然后把刚刚创建的SpriteAsset拖过来 放到对应的地方 然后…

牛客周赛 E-茜茜的计算器

原题链接&#xff1a;E-茜茜的计算器​​​​​​ 题目大意&#xff1a;在计算器上显示的0~9十个数字&#xff0c;如果这个计算器有n个位置&#xff0c;可以显示n个数字&#xff0c;问能显示多少种不同的对称数字。只能横轴和竖轴对称。 思路&#xff1a;容斥&#xff0c;最终…

Docker(二)-Centos7安装Docker并配置镜像加速

系统用户为非root用户 1.安装条件 确定Centos版本是否是7及以上sudo vim /etc/redhat-release2.官网地址 https://docs.docker.com/engine/install/centos3.卸载已安装的旧版本 sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-lates…

数字孪生定义及应用介绍

数字孪生定义及应用介绍 1 数字孪生&#xff08;Digital Twin, DT&#xff09;概述1.1 定义1.2 功能1.3 使用场景1.4 数字孪生三步走1.4.1 数字模型1.4.2 数字影子1.4.3 数字孪生 数字孪生地球平台Earth-2 参考 1 数字孪生&#xff08;Digital Twin, DT&#xff09;概述 数字孪…

项目(一)--高并发内存池项目简介

什么是高并发内存池 它是一个全球性大厂google(谷歌)的 开源项目,项目名字叫tcmalloc,全称是Thread-Caching Malloc,即线程缓存的malloc 作用&#xff1a; 我们知道C语言在堆上开辟空间和 释放使用的是malloc和free函数 并且C的动态内存管理new和delete 的底层实际上也调用了…

白酒行业数字化营销转型方向

白酒行业正站在数字化营销的新风口&#xff0c;随着科技的迅猛发展和消费者行为模式的变革&#xff0c;这一传统行业正迎来前所未有的发展机遇。数字化营销不仅为白酒企业打开了新的市场大门&#xff0c;更在重塑消费者与品牌之间的关系&#xff0c;推动行业向更智能、更个性化…

day02论文学习:能够使大语言模型产生带有引用的文章

1.主题&#xff1a;Enabling Large Language Models to Generate Text with Citations&#xff08;能够使大语言模型产生带有引用的文章&#xff09; 引用出处&#xff1a; Gao, T., Yen, H., Yu, J., & Chen, D. (2023). Enabling Large Language Models to Generate Tex…

05通讯录管理系统——添加联系人

功能描述&#xff1a;实现添加联系人功能&#xff0c;联系人上限为1000人&#xff0c;联系人信息包括姓名、性别、年龄、联系电话、家庭住址。 添加联系人实现步骤&#xff1a; 1.设计联系人结构体 2.设计通讯录结构体 3.main函数中创建通讯录 4.封装添加联系人函数 5.测…

2024-06-17 问AI: 在深度学习中,harmonic mean是什么?

文心一言 在深度学习中&#xff0c;**harmonic mean&#xff08;调和平均数&#xff09;**是一个用于评估模型性能的指标&#xff0c;特别是在处理不平衡的数据集或需要综合多个评估指标的场景中。以下是关于harmonic mean在深度学习中应用的详细解释&#xff1a; 定义&#…

多态深度剖析

前言 继承是多态的基础&#xff0c; 如果对于继承的知识还不够了解&#xff0c; 可以去阅读上一篇文章 继承深度剖析 基本概念与定义 概念&#xff1a; 通俗来说&#xff0c;就是多种形态。具体点就是去完成某个行为&#xff0c; 当不同的对象去完成时会产生出不同的状…

湿法消解石墨消解仪 应用化学分析领域石墨炉

石墨消解仪在化学实验中具有重要的作用。它是一种高级实验设备&#xff0c;广泛应用于化学分析领域&#xff0c;特别是在样品的前处理和测试前的样品制备过程中。 石墨消解仪采用高温高压技术&#xff0c;能够将固体样品中的有机和无机物质转化为可溶性的气体或液体形式。这种…

Aeron:两个代理之间的单向IPC(One-way IPC between two agents)

一、概述 本例展示了如何通过 IPC 在调度于不同线程的两个代理之间传输缓冲区。在继续学习本示例之前&#xff0c;最好先复习一下Simplest Full Example &#xff0c;因为该示例展示的是 IPC 通信&#xff0c;没有增加代理的复杂性。读者还应熟悉Media Driver 流程构建如下&…

结合Boosting理论与深度ResNet:ICML2018论文代码详解与实现

代码见&#xff1a;JordanAsh/boostresnet: A PyTorch implementation of BoostResNet 原始论文&#xff1a;Huang F, Ash J, Langford J, et al. Learning deep resnet blocks sequentially using boosting theory[C]//International Conference on Machine Learning. PMLR, 2…

英特尔 “AI” 科通:英特尔AI大模型应用前瞻

亲爱的科技探险家、前沿探索者、对未来深具好奇心的您&#xff0c; 身处人工智能引领的时代&#xff0c;我们目睹着行业的革命性变革。技术的创新不仅改变着我们的日常&#xff0c;更重新定义着我们对未来的期许。今天&#xff0c;怀着无限激情和期待&#xff0c;我们邀请您参…

国际数字影像产业园:建设与推动企业孵化与梯次培育

国际数字影像产业园在建设与推动企业孵化及梯次培育方面取得了显著成效。未来&#xff0c;随着技术的不断进步和市场的不断扩大&#xff0c;园区将继续发挥其在数字经济产业中的引领作用&#xff0c;为文化产业的发展贡献更多力量。 一、企业孵化与入驻 企业入驻情况&#xff…

物联边缘网关如何助力工厂实现智能化生产?以某智能制造工厂为例-天拓四方

随着工业4.0的深入推进&#xff0c;智能制造工厂成为了工业发展的重要方向。在这个背景下&#xff0c;物联边缘网关以其独特的优势在智能制造工厂中发挥着越来越重要的作用。以下将通过一个具体的智能制造工厂应用案例&#xff0c;来阐述物联边缘网关如何助力工厂实现智能化生产…