qt-C++笔记之父类窗口、父类控件、对象树的关系

qt-C++笔记之父类窗口、父类控件、对象树的关系

在这里插入图片描述

code review!

参考笔记
1.qt-C++笔记之父类窗口、父类控件、对象树的关系
2.qt-C++笔记之继承自 QWidget和继承自QObject 并通过 getWidget() 显示窗口或控件时的区别和原理
3.qt-C++笔记之自定义类继承自 QObjectQWidget 及开发方式详解

文章目录

  • qt-C++笔记之父类窗口、父类控件、对象树的关系
    • 一.第一次笔记
      • 1. 父类窗口与父类控件是什么?
      • 2. 传入的 `this` 和传入的父类窗口
      • 3. 跨层级的父子关系
      • 4. 纯代码开发
        • a. 创建 `MyObject` 并传入 `this` 作为父对象
        • b. 创建 `MyWidget` 并传入父窗口
      • 5. 使用 Qt Designer 拖拽控件开发:通过 Qt Designer 创建 UI,并在代码中设置父对象
      • 6. 传入 `this` 作为父对象:在自定义控件中创建子控件
      • 7. 传入具体的父类窗口:从一个窗口创建子控件,并指定不同的父窗口
      • 8. 跨层级的父子关系
        • a. 多层级父子关系示例
        • b. 跨不同逻辑层级的父子关系
    • 二.第二次笔记
      • 示例一:头文件和源文件分离
      • 示例二:一个完整的main.cpp
      • 示例三:入参为this指针的情况

一.第一次笔记

1. 父类窗口与父类控件是什么?

父类窗口(Parent Window)父类控件(Parent Widget)指的是在Qt的对象树(Object Tree)中,某个窗口或控件的直接上级对象。具体来说:

  • 父类窗口通常指的是一个顶层窗口(如 QMainWindowQDialog),它可以包含多个子控件(widgets)。
  • 父类控件是指一个控件(如按钮、标签等)的直接父级控件。通过父子关系,子控件会在父控件的坐标系统内进行定位和显示。

父子关系的作用包括:

  • 内存管理:在Qt中,父对象会自动管理其子对象的生命周期。当父对象被销毁时,所有子对象也会被自动销毁,避免内存泄漏。
  • 层次结构:通过父子关系,Qt能够正确地渲染和管理窗口及控件的显示层级。

例如

声明:MyObject(QObject *parent = nullptr);
定义:MyObject::MyObject(QObject *parent) : QObject(parent) {}

声明:MyWidget(QWidget *parent = nullptr);
定义:MyWidget::MyWidget(QWidget *parent) : QWidget(parent) {}

在这里,MyObject继承自QObject,而MyWidget继承自QWidget。每个构造函数都接受一个指向父对象的指针,并通过初始化列表将其传递给基类构造函数。这意味着创建MyObjectMyWidget实例时,可以指定它们的父对象,从而建立父子关系。

2. 传入的 this 和传入的父类窗口

在Qt中,创建子对象时通常需要传递一个父指针,以建立父子关系。常见的做法包括:

  • 传入 this

    • 当你在一个类的成员函数中创建子对象时,通常会传入this指针作为父对象。
    • 例如,在一个窗口类中创建一个按钮:
      QPushButton *button = new QPushButton("Click Me", this);
      
    • 这里,this指向当前窗口对象,按钮将成为该窗口的子控件。
  • 传入具体的父类窗口

    • 有时需要将子对象附加到特定的父窗口,而不是当前对象。
    • 例如,在一个对话框中创建一个控件,并将主窗口作为父对象:
      QPushButton *button = new QPushButton("Click Me", mainWindow);
      
    • 这样,按钮的生命周期将与mainWindow绑定,而不是当前对话框。

3. 跨层级的父子关系

跨层级的父子关系指的是子对象的父对象不在直接的层级结构中。例如:

  • 一个顶层窗口(如MainWindow)包含一个中间层的控件(如QWidget),该控件再包含其他子控件。
  • 或者,一个对象的父对象在不同的逻辑层级中,如业务逻辑对象的父对象是一个UI对象。

示例

// MainWindow 是顶层窗口
MainWindow *mainWindow = new MainWindow();

// 中间层控件
QWidget *centralWidget = new QWidget(mainWindow);

// 子控件
QPushButton *button = new QPushButton("Click Me", centralWidget);

在这个例子中,button的父对象是centralWidget,而centralWidget的父对象是mainWindow。这种多层级的父子关系有助于组织复杂的界面结构,并确保对象的生命周期由顶层对象统一管理。

4. 纯代码开发

a. 创建 MyObject 并传入 this 作为父对象
// MyClass.h
#include <QObject>

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

// MyClass.cpp
#include "MyClass.h"

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

// Usage in another class
#include "MyClass.h"

class AnotherClass : public QObject {
    Q_OBJECT
public:
    AnotherClass() {
        MyObject *obj = new MyObject(this); // 'this' 是 AnotherClass 的实例
    }
};

说明:AnotherClass 中创建 MyObject 实例时,将 this 作为父对象传递,确保 MyObject 的生命周期与 AnotherClass 绑定。

b. 创建 MyWidget 并传入父窗口
// MyWidget.h
#include <QWidget>

class MyWidget : public QWidget {
    Q_OBJECT
public:
    explicit MyWidget(QWidget *parent = nullptr);
};

// MyWidget.cpp
#include "MyWidget.h"

MyWidget::MyWidget(QWidget *parent) : QWidget(parent) {}

// Usage in MainWindow
#include "MyWidget.h"
#include <QMainWindow>

class MainWindow : public QMainWindow {
    Q_OBJECT
public:
    MainWindow() {
        MyWidget *widget = new MyWidget(this); // 'this' 是 MainWindow 的实例
        setCentralWidget(widget);
    }
};

说明:MainWindow 中创建 MyWidget 实例时,将 this 作为父窗口传递,使 MyWidget 成为 MainWindow 的中央控件。

5. 使用 Qt Designer 拖拽控件开发:通过 Qt Designer 创建 UI,并在代码中设置父对象

假设你使用 Qt Designer 创建了一个 MainWindow,并在其中放置了一个自定义控件 MyWidget

// mainwindow.ui
<!-- 在 Qt Designer 中拖拽一个 QWidget 并提升为 MyWidget -->

<widget class="QMainWindow" name="MainWindow">
    <widget class="MyWidget" name="myWidget" />
</widget>
// mainwindow.h
#include <QMainWindow>
#include "MyWidget.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow {
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
private:
    Ui::MainWindow *ui;
};

// mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    // Qt Designer 已经自动将 MyWidget 的父对象设置为 MainWindow
}

MainWindow::~MainWindow() {
    delete ui;
}

说明: 使用 Qt Designer 拖拽 MyWidgetMainWindow,Designer 自动将 MyWidget 的父对象设置为 MainWindow,无需手动传递父指针。

6. 传入 this 作为父对象:在自定义控件中创建子控件

// MyWidget.cpp
#include "MyWidget.h"
#include <QPushButton>

MyWidget::MyWidget(QWidget *parent) : QWidget(parent) {
    QPushButton *button = new QPushButton("Click Me", this); // 'this' 是 MyWidget 的实例
    button->setGeometry(10, 10, 100, 30);
}

说明:MyWidget 的构造函数中创建一个 QPushButton,并将 this 作为父对象,使按钮成为 MyWidget 的子控件。

7. 传入具体的父类窗口:从一个窗口创建子控件,并指定不同的父窗口

#include <QMainWindow>
#include "MyWidget.h"

class MainWindow : public QMainWindow {
    Q_OBJECT
public:
    MainWindow() {
        QWidget *central = new QWidget(this);
        setCentralWidget(central);

        MyWidget *widget = new MyWidget(central); // 指定 central 为父对象
    }
};

说明: MyWidget 的父对象被指定为 central,而不是直接是 MainWindow,使其生命周期与 central 相关联。

8. 跨层级的父子关系

a. 多层级父子关系示例
#include <QMainWindow>
#include "MyWidget.h"
#include "MyObject.h"

class MainWindow : public QMainWindow {
    Q_OBJECT
public:
    MainWindow() {
        // 创建顶层控件
        MyWidget *widget = new MyWidget(this);
        setCentralWidget(widget);

        // 在 MyWidget 中创建 MyObject
        MyObject *obj = new MyObject(widget); // widget 作为 MyObject 的父对象
    }
};

说明: 这里 MyObject 的父对象是 MyWidget,而 MyWidget 的父对象是 MainWindow。这种跨层级的父子关系确保了对象的生命周期由顶层对象统一管理。

b. 跨不同逻辑层级的父子关系

假设有一个业务逻辑类 BusinessLogic 继承自 MyObject,需要将其父对象设置为 UI 层的 MainWindow

// BusinessLogic.h
#include "MyObject.h"

class BusinessLogic : public MyObject {
    Q_OBJECT
public:
    explicit BusinessLogic(QObject *parent = nullptr);
};

// BusinessLogic.cpp
#include "BusinessLogic.h"

BusinessLogic::BusinessLogic(QObject *parent) : MyObject(parent) {}

// Usage in MainWindow
#include "BusinessLogic.h"

class MainWindow : public QMainWindow {
    Q_OBJECT
public:
    MainWindow() {
        BusinessLogic *logic = new BusinessLogic(this); // 'this' 是 MainWindow
    }
};

说明: BusinessLogic 的父对象是 MainWindow,尽管它属于业务逻辑层,但通过这种方式可以确保其生命周期与 UI 层关联。

二.第二次笔记

示例一:头文件和源文件分离

// MyObject.h
#ifndef MYOBJECT_H
#define MYOBJECT_H

#include <QObject>

class MyObject : public QObject
{
    Q_OBJECT

public:
    explicit MyObject(QObject *parent = nullptr); // 构造函数声明,默认 parent 为 nullptr
};

#endif // MYOBJECT_H

// MyObject.cpp
#include "MyObject.h"

MyObject::MyObject(QObject *parent) : QObject(parent) {} // 构造函数定义,初始化基类 QObject 并传递 parent

// MyWidget.h
#ifndef MYWIDGET_H
#define MYWIDGET_H

#include <QWidget>

class MyWidget : public QWidget
{
    Q_OBJECT

public:
    explicit MyWidget(QWidget *parent = nullptr); // 构造函数声明,默认 parent 为 nullptr
};

#endif // MYWIDGET_H

// MyWidget.cpp
#include "MyWidget.h"

MyWidget::MyWidget(QWidget *parent) : QWidget(parent) {} // 构造函数定义,初始化基类 QWidget 并传递 parent

// main.cpp
#include <QApplication>
#include "MyObject.h"
#include "MyWidget.h"

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

    MyObject *obj = new MyObject(); // 实例化 MyObject,没有指定父对象
    MyObject *objWithParent = new MyObject(nullptr); // 实例化 MyObject,并指定 parent 为 nullptr(等同于不指定)
    MyWidget *widget = new MyWidget(); // 实例化 MyWidget,没有指定父窗口
    MyWidget *widgetWithParent = new MyWidget(nullptr); // 实例化 MyWidget,并指定 parent 为 nullptr(等同于不指定)

    widget->show(); // 显示 MyWidget 窗口

    return app.exec(); // 运行应用程序事件循环
}

示例二:一个完整的main.cpp

// main.cpp
// 这个程序演示了 Qt 中 QObject 和 QWidget 的父子关系

#include <QApplication>
#include <QObject>
#include <QWidget>
#include <QDebug>

class MyObject : public QObject
{
    Q_OBJECT

public:
    explicit MyObject(QObject *parent = nullptr) : QObject(parent) { // 构造函数,默认 parent 为 nullptr
        if (parent)
            qDebug() << "MyObject 被创建,父对象为:" << parent;
        else
            qDebug() << "MyObject 被创建,没有父对象";
    }

    ~MyObject() { qDebug() << "MyObject 被销毁"; } // 析构函数
};

class MyWidget : public QWidget
{
    Q_OBJECT

public:
    explicit MyWidget(QWidget *parent = nullptr) : QWidget(parent) { // 构造函数,默认 parent 为 nullptr
        if (parent)
            qDebug() << "MyWidget 被创建,父窗口为:" << parent;
        else
            qDebug() << "MyWidget 被创建,没有父窗口";
    }

    ~MyWidget() { qDebug() << "MyWidget 被销毁"; } // 析构函数
};

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

    MyObject *obj1 = new MyObject(); // 创建一个没有父对象的 MyObject 实例,obj1 没有父对象,需手动删除
     
    MyObject *obj2 = new MyObject(obj1); // 创建一个指定父对象为 obj1 的 MyObject 实例
    MyWidget *widget1 = new MyWidget(); // 创建一个没有父窗口的 MyWidget 实例
    widget1->setWindowTitle("没有父窗口的 MyWidget"); // 设置窗口标题
    widget1->resize(300, 200); // 调整窗口大小
    widget1->show(); // 显示窗口

    MyWidget *widget2 = new MyWidget(widget1); // 创建一个指定父窗口为 widget1 的 MyWidget 实例
    widget2->setWindowTitle("widget1 的子窗口 MyWidget");
    widget2->resize(200, 150);
    widget2->show();

    MyObject *obj3 = new MyObject(nullptr); // 创建一个没有父对象的 MyObject 实例,传递 nullptr,obj3 没有父对象,需手动删除
    
    MyObject *obj4 = new MyObject(widget1); // 创建一个指定父对象为 widget1 的 MyObject 实例

    MyWidget *widget3 = new MyWidget(nullptr); // 设置一个父窗口为 nullptr 的 MyWidget 实例
    widget3->setWindowTitle("没有父窗口的另一个 MyWidget");
    widget3->resize(250, 180);
    widget3->show();

    return app.exec(); // 运行应用程序事件循环

    // 注意:obj1, obj3 没有父对象,程序退出时会自动销毁
    // 在更复杂的应用中,应手动删除没有父对象的堆对象以避免内存泄漏
}

#include "main.moc"

示例三:入参为this指针的情况

项目结构

MyQtApp/
├── main.cpp
├── ParentWidget.h
├── ParentWidget.cpp
├── MyWidget.h
├── MyWidget.cpp
├── MyObject.h
├── MyObject.cpp
└── MyQtApp.pro
    1. MyQtApp.pro
QT += widgets
CONFIG += c++11

SOURCES += main.cpp \
           ParentWidget.cpp \
           MyWidget.cpp \
           MyObject.cpp

HEADERS += ParentWidget.h \
           MyWidget.h \
           MyObject.h
    1. main.cpp
#include <QApplication>
#include "ParentWidget.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    ParentWidget parentWidget;
    parentWidget.setWindowTitle("ParentWidget 主窗口");
    parentWidget.resize(400, 300);
    parentWidget.show();
    return app.exec();
}
    1. ParentWidget.h
#ifndef PARENTWIDGET_H
#define PARENTWIDGET_H

#include <QWidget>
#include "MyObject.h"
#include "MyWidget.h"

class ParentWidget : public QWidget
{
    Q_OBJECT
public:
    explicit ParentWidget(QWidget *parent = nullptr);
};

#endif // PARENTWIDGET_H
    1. ParentWidget.cpp
#include "ParentWidget.h"
#include <QDebug>

ParentWidget::ParentWidget(QWidget *parent) : QWidget(parent)
{
    MyWidget *childWidget = new MyWidget(this);
    childWidget->setWindowTitle("ParentWidget 的子窗口 MyWidget");
    childWidget->resize(200, 150);
    childWidget->show();

    MyObject *childObject = new MyObject(this);
    qDebug() << "创建了 MyObject:" << childObject;
}
    1. MyWidget.h
#ifndef MYWIDGET_H
#define MYWIDGET_H

#include <QWidget>

class MyWidget : public QWidget
{
    Q_OBJECT
public:
    explicit MyWidget(QWidget *parent = nullptr);
};

#endif // MYWIDGET_H
    1. MyWidget.cpp
#include "MyWidget.h"

MyWidget::MyWidget(QWidget *parent) : QWidget(parent)
{
    // 初始化内容(可选)
}
    1. MyObject.h
#ifndef MYOBJECT_H
#define MYOBJECT_H

#include <QObject>

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

#endif // MYOBJECT_H
    1. MyObject.cpp
#include "MyObject.h"

MyObject::MyObject(QObject *parent) : QObject(parent)
{
    // 初始化内容(可选)
}

预期效果

运行程序后,将显示一个标题为“ParentWidget 主窗口”的主窗口,同时弹出一个标题为“ParentWidget 的子窗口 MyWidget”的子窗口。控制台会输出创建 MyObject 的信息。

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

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

相关文章

VMware ubuntu12.04怎么设置静态IP联网

记得刚开始学习嵌入式就是从ubuntu12.04的环境开始学习的C语言&#xff0c;当时没有弄清楚怎么设置静态IP联网&#xff0c;现在写一篇文章。 1.首先&#xff0c;关闭ubuntu的网络&#xff1b; 2.电脑使用的是wifi,将VMware桥接到该网卡上&#xff1b; 3.在虚拟机设置里面选择桥…

计算机视觉中的图像滤波与增强算法

摘要&#xff1a; 本文深入探讨了计算机视觉领域中的图像滤波与增强算法。首先介绍了图像滤波与增强的基本概念和重要性&#xff0c;随后详细阐述了线性滤波算法中的均值滤波和高斯滤波&#xff0c;以及非线性滤波算法中的中值滤波和双边滤波&#xff0c;包括它们的原理、数学模…

AI大模型学习笔记|神经网络与注意力机制(逐行解读)

来源分享链接&#xff1a;通过网盘分享的文件&#xff1a;详解神经网络是如何训练的 链接: https://pan.baidu.com/s/12EF7y0vJfH5x6X-0QEVezg 提取码: k924 内容摘要&#xff1a;本文深入探讨了神经网络与注意力机制的基础&#xff0c;以及神经网络参数训练的过程。以鸢尾花数…

腾讯云系统盘扩容

在腾讯云申请空间后&#xff0c;只要执行三行命令 云硬盘 在线扩展系统盘分区及文件系统-操作指南-文档中心-腾讯云 安装工具 yum install -y cloud-utils-growpart 给/eav/vda1扩分区 LC_ALLen_US.UTF-8 growpart /dev/vda 1 挂载扩容 ext4 文件系统 resize2fs /dev/vda1 …

【控制系统】深入理解反步控制(Backstepping) | 反步法控制器原理与应用实例解析(附Matlab/Simulink仿真实现)

&#x1f4af; 欢迎光临清流君的博客小天地&#xff0c;这里是我分享技术与心得的温馨角落 &#x1f4af; &#x1f525; 个人主页:【清流君】&#x1f525; &#x1f4da; 系列专栏: 运动控制 | 决策规划 | 机器人数值优化 &#x1f4da; &#x1f31f;始终保持好奇心&…

构建树莓派温湿度监测系统:从硬件到软件的完整指南

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

人工智能系统

介绍人工智能 的基础书 点击这里 1.1 深度学习的历史&#xff0c;现状与发展 本章将介绍深度学习的由来&#xff0c;现状和趋势&#xff0c;让读者能够了解人工智能系统之上的深度学习负载的由来与趋势&#xff0c;为后面理解深度学习系统的设计和权衡形成初步的基础。我们在后…

NVR小程序接入平台EasyNVR设置预置位显示“参数错误”的解决方法

视频监控技术在现代社会中的应用已经变得越来越广泛&#xff0c;从城市安防到家庭安全&#xff0c;从交通管理到商业监控&#xff0c;其作用无处不在。随着科技的不断进步&#xff0c;视频监控不仅提高了安全性&#xff0c;还带来了许多新的机遇和挑战。 近期&#xff0c;我们收…

下载红米Note 9 Pro5G对应的LineageOS代码下载及编译

构建 LineageOS 进入网站&#xff1a;Info about gauguin | LineageOS Wiki&#xff0c;点击&#xff1a;Build for yourself&#xff0c;里面有详细的教程&#xff0c;我这里就按照Note 9 Pro 5G来。 机器环境 Ubuntu环境为&#xff1a;20.04.6LinagesOS版本&#xff1a;21-…

如何在 Ubuntu 22.04 上安装 Strapi CMS

简介 Strapi 是一个使用 JavaScript 构建的开源、无头内容管理系统 (CMS)。与其他无头 CMS 一样&#xff0c;Strapi 开箱即用不带前端。它使用 API 作为其前端&#xff0c;允许你使用流行的框架&#xff08;如 React 和 Next.js&#xff09;构建网站。Strapi 基于插件系统&…

Java:集合(List、Map、Set)

文章目录 1. Collection集合1-1. 迭代器遍历方式1-2. 通过for循环进行遍历1-3. forEach遍历 2. List集合2-1. ArrayList底层实现原理2-2. LinkedList底层实现原理 3. Set集合3-1. HashSet 底层实现3-2. LinkedHashSet 底层实现3-3. TreeSet 4. Collection集合->总结5. Map集…

私有云dbPaaS为何被Gartner技术成熟度曲线标记为“废弃”?

当云计算席卷而来&#xff0c;基于云基础设施的数据库部署也改变了数据库。在传统的私有化部署&#xff08;On-premises&#xff09;和公有云部署&#xff08;Public Cloud&#xff09;之间&#xff0c;不断融合的混合IT&#xff08;Mixed IT&#xff09;形式成为最常见的企业级…

ElementPlus Table 表格实现可编辑单元格

通过基础的Table表格来实现单元格内容的可编辑 1.首先定位到需要编辑的列&#xff0c;替换el-table-column <el-table-column label"Editable Column" width"300"><template #default"{ row, column, $index }"><el-inputsize&qu…

《数据结构》(408代码题)

2009 单链表&#xff08;双指针&#xff09; 分析&#xff1a;首先呢&#xff0c;给我们的数据结构是一个带有表头结点的单链表&#xff0c;也不允许我们改变链表的结构。链表的长度不是直接给出的啊&#xff0c;所以这个倒数也很棘手。那我们该如何解决这个“k”呢&#xff0c…

Qt控件的盒子模型,了解边距边线和内容区

这篇专门讲讲一个控件在绘制时的视觉样式。我们平常在对控件设置样式时&#xff0c;需要设置控件的一些外边距&#xff0c;内边距&#xff0c;边线&#xff0c;还有文字内容&#xff0c;贴上图片等。那么对于一个控件&#xff0c;到底怎么实现这些设置的呢&#xff1f; 先看下面…

第十二课 Unity 内存优化_内存工具篇(Memory)详解

内存&#xff08;Memory&#xff09; unity 内存部分也是优化过程中非常重要的一个环节&#xff0c;也会影像渲染过程中的同步等待与带宽问题。因此内存的优化也可能会给我们渲染开销带来精简&#xff0c;今天我们先来了解unity中的内存与使用到的内存工具。 Unity中的内存 托…

windows mysql5.7设置慢查询参数

如果没有my.ini,可以复制一份my-default.ini改个名字就可以。 注意重启mysql服务 mysql5.7 直接在配置文件my.ini 中写如下配置 log_slow_admin_statements ON log_slow_slave_statements ON slow_query_log 1 //开启慢查询 &#xff08;很多博客说on off ,我本机my…

STM32F407+LAN8720A +LWIP +FreeRTOS ping通

使用STM32CUBEIDE自带的 LWIP和FreeROTS 版本说明STM32CUBEIDE 操作如下1. 配置RCC/SYS2. 配置ETH/USART3. 配置EHT_RESET/LED4. 配置FreeRTOS5. 配置LWIP6. 配置时钟7. 生成单独的源文件和头文件,并生成代码8. printf重定义9. ethernetif.c添加lan8720a复位10. MY_LWIP_Init …

【电脑技巧】将键盘的方向键映射为alt+i、k、j、l

最近感觉方向键太远了&#xff0c;想找个方法修改键盘映射&#xff0c;有几种方式可以实现 使用powertoys的键盘映射&#xff08;软件太大了&#xff0c;只为键盘映射不值得下这个&#xff09;使用autohotkey&#xff08;通过脚本的方式&#xff0c;可以打包成exe文件&#xf…

物联网中的数据收集:MQTT实现的比较

本篇论文的标题是《Data collection in IoT: A comparison of MQTT implementations》&#xff0c;中文可以翻译为《物联网中的数据收集&#xff1a;MQTT实现的比较》。论文由Erik Gustafsson和Ruben Jarefors撰写&#xff0c;导师是Jalal Maleki&#xff0c;评审员是Rita Kovo…