QT 学习笔记摘要(一)

第一节 QT介绍

 1. QT概述

        简单来说,QT就是一个跨平台的客户端技术,HTML画网页一样,而QT就是画客户端的,它不仅可以绘制界面而且可以做单机应用开发,还可以做网络程序的客户端界面开发

        更专业的说法是:Qt 是⼀个 跨平台的 C++ 图形⽤⼾界⾯应⽤程序框架 ,它拥有完备的C++ 图形库和集成了一系列代码模块简化难度,开发者可以通过简单的拖拽组合来实现复杂的应⽤程序,而且Qt 支持C++PythonQMLJavascript 等多种语言,适合多种技术、开发方式。同时Qt 也拥有一套完整的设计、开发工具以及丰富的文档和例程,其开源社区非常活跃,这些能明显降低开发难度和缩短开发时间

        其实除了QT是客户端技术,还有VB,C++、win32API 的 MFCWinform ,C# .net framework,Java swing/javaFx ,C++ duilib,Objective-c/swift cocoa等等

        但他们不是做出来的客户端界面丑,无法跨平台,没有活跃的社区,就是没有维护了,所以一般公司做客户端界面都是用的QT;

        而Qt是很多客户端跨平台的首选,因为开源、UI 库和各种功能的类库非常丰富,但这里只推荐做pc的客户端,移动端的客户端界面还是不推荐使用Qt

2. QT框架

        一句话:One framework. One codebase. Any platform,这是Qt 官网的一句话,很好的概括了什么是Qt,

口号说明:

  • One framework(一个框架):只需要使用一个开发框架
  • One codebase(一套代码):只需要维护一份代码,而不是针对不同平台写不同的代码
  • Any platform(任何平台):这套代码可以运行在多个平台上,比如 Windows、macOS、Linux,甚至移动设备(iOS/Android)或 Web 端

3. QT发展(了解)

  • Qt最早是1991年由挪威的Eirik Chambe-Eng和Haavard Nord开发的,1994年3月4日成立奇趣科技公司(Trolltech);

  • 2000年奇趣科技公司为开源社区发布了遵循 GPL(GNU General Public License)许可证的开源版本;

  • 2008年诺基亚公司收购了奇趣科技公司,并增加了 LGPL(GNU Lesser General Public License)的授权模式;

  • 2011年3月Qt 商业授权业务出售给了芬兰IT服务公司Digia

  • 2013年7月3日发布Qt5,2020年6月12日**Qt5.15** LTS 正式发布,目前已经推出Qt6。

        经过多年的发展,市面上也有很多基于Qt开发的应用程序:WPS、YY语音、豆瓣电台、虾米音乐、淘宝助理、千牛、暴雪的战网客户端、VirtualBox、Google地图、Photoshop等等

4. QT优点

  • 跨平台,⼏乎⽀持所有的平台;

  • 接⼝简单,容易上⼿,学习 QT 框架对学习其他框架有参考意义。

  • ⼀定程度上简化了内存回收机制

  • 开发效率⾼,能够快速的构建应⽤程序。

  • 有很好的社区氛围,市场份额在缓慢上升。

  • 可以进⾏嵌⼊式开发

5. Qt 的应⽤场景

  • 主要: 桌⾯应⽤程序, 嵌⼊式系统

  • 次要: 移动应⽤程序

        额外多说一下:嵌入式系统指的是日常使用的: 冰箱,洗衣机,路由器,投影仪...之类的,这些设备里面就使用了嵌入式系统

第二节 QT Creator

1. 下载

   https://download.qt.io/archive/qt/5.12/5.12.11/

虽然目前最新的QT版本是QT6,但是我这里使用的是QT5  

  • 我使用的是5.12.11版的qt,大家可以根据自己的实际情况进行下载,
  • 值得多说一句的是:类似于这些软件/工具的下载,不要最新的,也不要太老的
  • 最新的版本出了问题不好解决,太老的版本可能又会有兼容性问题

 2. 安装

说明一下:

  • 可能第一个界面是需要注册账号的,直接使用邮箱+密码注册,然后会给你的邮箱中发个邮件,最后你在你的邮箱中确认那个邮件就行了(如果在安装之间断网,那么就不需要注册账号)
  • 下一步,下一步,然后选择那四个组件就行了,不要全选

3. 配置环境变量 

        为了让操作系统/QT Creator工具,能够找到Qt SDK中提供的exe,也就是运行Qt 程序的时候,能够找到对应.dll 动态库,所以我们这里可以先把环境变量配置好

4. 基本介绍

        刚才其实我们就已经把QT开发环境下好了,可能桌面没有显示,按一下win键,如下图

5. 新建项目

  • 其实一路next下去也行

6. 项目结构

 6.1 qt_tmp.pro

qt_tmp.pro是项目的配置文件

说明一下:

  • 这里该怎么理解QT += 模块呢,其实就是我们在做大型项目是需要引入的第三方库,
  • 后面我们会需要引入multimedia 模块,而这个模块是跟音视频有关的模块,简单理解为第三方库也行

 6.2 mainwindow.h

说明一下:

  • Q_OBJECT其实是个宏,其中有QT中的信号与槽的宏定义,更详细的后面再说

关于QT中对头文件的设定:

  • 在使用Qt中内置的类时,一般来说包含头文件的名字就是和类名一致的,但是也不是所有的Qt类都需要显示包含头文件
  • 毕竟在c++中,一些头文件都是间接被包含的

关于构造函数中需要穿父类的指针说明:

  • QT中为了统一析构父类和子类,引入了对象树的概念(后面详细介绍)
  • 而创建对象时就需要把这个对象往树·上挂,而往树上挂就必须要指明父节点
  • 则构造的时候就需要传一个父类的指针

6.3 mainwindow.cpp

6.4 main.cpp

 说明一下:

  • 是先有应用,再有窗口,窗口是放在应用里的,可能有多个窗口,所以他们2个对象实例化的顺序不能颠倒

这里简单说一下a.exec(),其实可以简单的理解为一个死循环,但还做了一些其他的东西,

  • 如果没有最后一行代码,而是写成了return 0; 那么这个窗口会闪一下,就退出了
  • 简单解释:能出现窗口是因为有w.show();// 显示窗口,而w对象又是栈上开辟的,出了作用域就没了

顺便再说一下:w.show()

  • .show()方法表示让控件显示处理
  • .hide()方法表示让控件隐藏
  • widget的父类时QWidget,则上面的那两个方法都是QWidget提供的

6.5 mainwindow.ui

        上面那种格式是xml格式,而这里的xml格式就是去描述这个界面是怎么样的,进一步的qmake会调用相关的工具,依据这个xml文件生成一些c++代码,从而把完整的界面构建出来

6.6 临时文件

 

说明一下:

  • 在运行一次程序之后,就会在 项目并列的地方,多出一个"build-xxxx"目录
  • 这个目录里面就是该项目运行过程中,生成的一些临时文件

7. 第一个程序hello world

7.1 纯图形化方式

说明一下: 

  •  以图形化方式实现界面,主要是在qt designer 拖动控件调调属性

  • 而我刚才往界面上拖拽了一个QLabel控件,此时,ui文件的xml中就会多出来这一段代码
  • 进一步的qmake就会在编译项目的时候,基于这个内容,生成一段C++代码,通过这个C++代码构建出界面内容

7.2 纯代码方式

方式一:重建一个cpp文件

#include <iostream>
#include <QMainWindow>
#include <QLabel>
#include <QApplication>
using namespace std;int main(int argc, char *argv[])
{//    cout << "Hello World!" << endl;QApplication a(argc, argv);// 因为show这个方法本来就是QMainWindow类的,所以直接实例化这个类的对象就行QMainWindow w;w.setGeometry(0,0,800,600);w.setWindowTitle("第一个程序");QLabel* label = new QLabel(&w);// 对这个控件做相关属性设置label->setText("hello world");label->setGeometry(160,110,400,71);label->setStyleSheet("font: 75 20pt Consolas;");w.show();return a.exec();
}

 

方式二:重建一个qt设计类文件

说明一下: 

  • 一般通过代码来构造界面的时候,通常会把构造界面放到Widget/MainWindow的构造函数中
  • 这里的this指针,是给当前这个label对象,指定一个父对象(以后会说的对象树)
  • 在QT中的字符串和C++/C中的字符串是不一样的,当时C++/C的字符串不好,所以QT为了字节的开发能变的顺畅,就自己发明了一套轮子,搞了一系列基础类,来支持QT的开发,包括但不限于
    字符串->QString 动态数组->QVector 链表->QList 字典->QMap
  • 在QString中也提供了 C风格字符串作为参数的构造函数,不显示构造QString,上述代码中,C风格字符串也会隐式构造成QString对象 
  • 每个标签都有一个同名的头文件,但有时候也会被其他头文件间接包含,
    比如: QString 对应的头文件,已经被很多Qt内置的其他类给间接包含了,因此一般不需要显示包含QString头文件

这里还有一个值得思考的点: 一个对象new出来了,但是却没有delete,这难道不会造成内存泄漏吗

  • ​​​​在上述代码中,Qt不会产生内存泄漏,label对象会在合适的时候被析构函数释放~~
  • 之所以能够把对象释放掉,主要是因为把这个对象挂到了对象树上了,交给Qt的对象树统一管理
  • 如果这个对象是在栈上创建的话,就有可能会存在一些"提前释放"的问题,此时就会导致对应的控件就在界面上不存在了
  • 推荐: 在堆上创建对象,并挂在对象树上

7.3 验证对象树会统一析构

  • 注: 上面少写了个delete
  •  自己实现label类,并继承QLabel,然后再自主实现析构函数
  • 则可以在输出日志中观察到 自己实现的析构函数被调用了,则对象树的确会统一析构
  • 这里使用qDebug进行输出日志(不建议使用cout),还有一个好处->可以进行统一关闭
    输出日志一般是在开发阶段,调试程序的时候使用

8. 快捷键

  • 注释:ctrl + /
  • 运⾏:ctrl + R
  • 编译:ctrl + B
  • 字体缩放:ctrl + ⿏标滑轮
  • 查找:ctrl + F
  • 整⾏移动:ctrl + shift + ⬆/⬇
  • 帮助⽂档:F1
  • ⾃动对⻬:ctrl + i
  • 同名之间的 .h 和 .cpp 的切换:F4

  • ⽣成函数声明的对应定义: alt + enter

9. 使⽤帮助⽂档 

  • 方法一:光标放到要查询的类名/⽅法名上, 直接按 F1(推荐)

  • 方法二:Qt Creator 左侧边栏中直接⽤⿏标单击 "帮助" 按钮

  • 方法三:找到 Qt Creator 的安装路径,在 "bin" ⽂件夹下找到 assistant.exe,双击打开;

10. Qt 中的命名规范

  • 类名:⾸字⺟⼤写,单词和单词之间⾸字⺟⼤写;MyClass  MyAdd

  • 函数名及变量名:⾸字⺟⼩写,单词和单词之间⾸字⺟⼤写;studentCount

11. Qt 窗⼝坐标体系

计算机中的坐标系和数学中的坐标系是不一样的,y轴是向下增长的

 


 

说明一下: 

  •  对于嵌套窗口,其坐标是相对于父窗口来说的

第三节 信号与槽

1. 基本概念

信号信号就是一个通知机制,比如在某个状态做了一个什么事情,或者状态发生了改变,需要有别人来处理的时候,就要发出一个信号,就相当于发出一个通知,信号是没有实现的,信号的成员函数是不需要被定义的

槽函数:信号发出去以后,一定要做一件事情,而这个事情就是由槽函数来做的,简单来说就是对信号做出的一种响应


         在QT中信号和槽函数一定要先进行绑定才可以的,且一定是先关联信号再进行绑定(顺序不能颠倒),后续只要信号触发了,Qt就会自动执行槽函数

        信号与槽这种机制是QT框架很重要的机制,它的优点有:松散耦合,但缺点:效率较低

2. 图形化操作

        比如我现在要在窗口中放置一个按钮,当我点击这个按钮的时候,这个窗口就会关闭 

        注意在ui界面中改了控件名字,是需要重新构建的,否则控件名将不会生效 

2.1 编写槽函数

        在ui界面中选中控件,然后右键转到槽,然后选择对应的信号

         之后在头文件对应的类中就会自动生成一个信号,并把光标跳转到自动生成的槽函数中

void MainWindow::on_pushButton_clicked()
{// 关闭窗口this->close();
}

说明一下:

  • 通过图形化界面的方式定义槽函数,的确很方便,很多步骤它都帮我们做完了
  • 但在真实的开发环境中我们需要自定义信号,自定槽函数,自己去关联信号与槽函数,

3. 纯代码操作 

 3.1 connect函数

        在 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: 描述了这个控件怎么处理(要处理信号的对象提供成员函数)

    3.2 深度理解connect函数参数

    • 我们上面传信号和槽都是传递的函数指针,而在C++中是不允许使用2个不同指针类型,相互传参相互赋值的(函数传参,本质就是赋值)
    • 其实这个函数声明是以前旧版本的QT的connect函数声明,以前个信号参数传参,要搭配要给SIGNAL宏,给槽函数传参要搭配一个SLOT宏(这样做的目的是 将 传入参数 转成char*)
    • connect(button,SIGNAL(&QPuhsButton::clicked),this,SLOT(&Widget::close))

    但是后来因为书写起来太麻烦了,在Qt5时进行了改进

    •  使用模板实现泛型编程,重载构造函数  
    •   此时connect函数就有一定的参数检查功能:参数1和参数2不匹配 or 参数3和参数4不匹配,
      都会编译出错
    • 则要求参数2必须是参数1的成员函数,参数4必须是参数3的成员函数

    4. 查看信号与槽

     自己平时的积累 + 查看文档

    •  QPushButton自己本身没有clicked信号,但是它继承了QAbstractButton
    • 在QAbstractButton中就有一个clicked点击信号
    • 注: 这个QAbstractButton又使继承QWidget

    •  我们写的widget在定义的时候就是继承QWidget的,而QWidget就有close这个关闭槽
    • 注: QWidget这个类又是继承自QObject类的

    5. 自定义槽

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

    5. 自定义信号

    • 自定义信号,本质就是一个函数,只需要声明就行了,而这个函数的定义,是Qt在编译过程中,动生成的(我们无法干预)
    • 而作为信号参数,这个函数的返回值,必须是void的,有没有参数都是可以的,甚至可以支持重载
    • Qt内置的信号,不需要手动触发,而自定义信号,需要手动代码触发  emit mySignal();
    • 这里使用图形化方式创建一个按钮,在通过这个按钮发送 自定义信号
    • 发送信号的操作, 也可以在任意合适的代码中. 不一定非得在构造函数里

    6. 带参数的信号与槽

    •  带有参数的信号,要求信号的参数和槽的参数要一致

    • 类型,个数要满足要求(信号的参数个数要多于槽的参数个数)

    7. 额外说明

    7.1 前置条件

    •  Qt 中如果要让某个类能够使用信号槽(可以在类中定义信号和槽函数),则必须要在类最开始的地方,写下Q_OBJECT
    • 将这个宏展开,会得到一大段代码,然后而这一大段代码又可以展开

    7.2 设计目的

    • 解耦,: 把触发 用户操作的控件 和 处理对应用户的操作逻辑 解耦合
    • 实现"多对多"效果
      一个信号,可以connect到多个槽函数上
      一个槽函数也可以被多个信号connect
    • 但是多对多的需求实际中并不常见,所以以后图形化开发框架都没有支持多对多

    7.3 disconnect断开连接

    主动断开往往是把信号重新绑定到另一个槽函数上

    • 如果没有 disconnect, 就会构成 一个信号绑定了两个槽函数. 触发信号的时候, 两个槽函数都会执行

    7.4 lambda表达式 

    定义槽函数的时候 也是可以使用lambda表达式的,

    •  为了解决lambda访问作用域的问题,就需要引入变量捕捉的语法规则
    • lambda语法是c++11中引入的,对于Qt5及其更高版本,默认就是按照c++ 11来编译的
    • 如果使用Qt4或者更老的版本,就需要手动在.pro文件中加上C++的编译选项:CONFIG += c++11

    8. 登录案例(动手)

            我们要实现的是一个登录注册的页面,具体参考下图:

    要求说明:

    •  实现一个登录系统的主页面,2个功能,一个登录,一个注册
    • 登录成功,需要跳转到欢迎界面,并欢迎这个登录的用户
    • 注册成功,需要跳转到主页面,并把注册到的信息填入对于的输入框中
    • ..... 

    注意 信号与槽不能嵌套,且电脑分辨率不同,会对qt designer产生影响

    4.1 关键点:如何新建一个窗口 

     

    说明一下:

    • 然后选择对应的控件就行了 

    4.2 关键点:如何展示子类的页面

            推荐:在父类中添加一个成员变量,类型是子类的类型,然后在构造函数中实例化这个对象,如下:

            而想要展示一个页面直接调用show方法,关闭一个页面直接调用hide方法

    4.3 关键点:如何把父类的数据传递给子类

            可以使用信号与槽,但这里推荐直接传递参数就可以了,处理参数的函数在子类中实现就可以了, 毕竟父类中有个成员变量是指向子类的(具体情况如上)

    4.4 关键点:如何把子类的数据传递给父类

            推荐:使用自定义信号与槽,首先在子类中自定义一个信号,然后再父类的构造函数中connect自定义信号与槽,然后再子类中要传数据的地方emit自定义信号,对了槽函数需要在父类中实现

    第四节 Qt Core

    Qt Core也就是Qt的核心部分

     

    1. QString常见函数

    1.1 append - 字符串拼接

    void function1()
    {QString str = "123456";str.append("abc");// 字符串拼接qDebug() << str;
    }

    1.2 prepend - 头前拼接

    void function2()
    {QString str = "123456";str.prepend("abc");// 字符串拼接qDebug() << str;
    }

    1.3 arg - 格式化

    void function3()
    {QString str = "姓名:%1,年龄:%2,性别:%3";QString format = str.arg("张三").arg(30).arg("男");qDebug() << format;
    }

    1.4  contains - 判断是否包含

    void function4()
    {QString str = "123abc456";if(str.contains("abc")){qDebug() << "包含abc" << endl;}else{qDebug() << "不包含abc" << endl;}
    }

    1.5 isEmpty && isNull

    void function5()
    {QString str1 = "";QString str2;if(str1.isEmpty()){qDebug() << "str1是empty的" << endl;}if(str1.isNull()){qDebug() << "str1是null的" << endl;}if(str2.isEmpty()){qDebug() << "str2是empty的" << endl;}if(str2.isNull()){qDebug() << "str2是null的" << endl;}
    }

    说明一下:

    • isEmpty()是用来判断字符串是否是空字符串的
    • isNull()既能判断是否是NULL,而且还能判断是不是空字符串

    1.6 startWith -- 判断是否以xxxxx打头

    void function6()
    {QString str = "123456";if(str.startsWith("123")){qDebug() << "str是以12打头的" << endl;}
    }

     

    1.7 indexOf - 找xxx出现的位置

    void function7()
    {QString str1 = "www.baidu.com";//找第一次.出现的位置qDebug() << str1.indexOf(".") << endl;
    }

     

    说明一下:

    • 这个函数就类似于c++中的find函数
    • 同理下标索引也是从0开始的

    1.8 repalce - 替换

    QString &QString::replace(int position, int n, const QString &after)

    参数说明:

    • 第一个参数是被替换字符串的位置
    • 第二个参数是被替换字符串的长度
    • 第三个参数是新的字符串
    void function8()
    {QString str1 = "www.baidu.com";//找第一次.出现的位置QString target = ".";int index = str1.indexOf(target);str1.replace(index,target.length(),"//");qDebug() << str1 << endl;
    }

     1.9 split - 分割字符串

    void function9()
    {QString str = "111:222:333:444";// 将str按照:分割成4个子字符串QStringList list = str.split(":");qDebug() << list << endl;
    }

    说明一下:

    •  split的返回值是QStringList类型,而这个类型就相当于一个只能存放QString的vector

    1.10 string 与 QString相互转换 

    • QString::fromStdString(s);// 把std::string 转换成QString
    • s.toStdString();//把QString转换成std::string

    2. QByteArray

    多用于处理字节数组 

    void function1()
    {QString str = "123456";QByteArray data = str.toUtf8();QString str1 = QString(data);qDebug() << str1 << endl;
    }

    3. QStringList && QVector

     QStringLis等价于QVector<QString>

    void function2()
    {QStringList v1 = {"ab"};v1.push_back("cd");for(auto e : v1){qDebug() << e << " ";}QVector<QString> v2 = {"ab"};v2.push_back("cd");for(auto e : v2){qDebug() << e << " ";}
    }

     

    说明一下:

    •  除了QVector还有QListQStack等等,前面已经说了QT它又搞了一套新的轮子,
    • 其实就是又封装了一遍

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

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

    相关文章

    QCustomPlot 叠加对象(Overlay Items)

    QCustomPlot 提供了一系列可以在图表上叠加显示的对象&#xff08;items&#xff09;&#xff0c;这些对象不属于数据本身&#xff0c;而是用于标注、辅助线等用途。以下是主要叠加对象的详细说明和使用方法。 1. QCPItemStraightLine (无限直线) 特性&#xff1a; 无限延伸的…

    Flink源码阅读环境准备全攻略:搭建高效探索的基石

    想要深入探索Flink的底层原理&#xff0c;搭建一套完整且适配的源码阅读环境是必经之路。这不仅能让我们更清晰地剖析代码逻辑&#xff0c;还能在调试过程中精准定位关键环节。接下来&#xff0c;结合有道云笔记内容&#xff0c;从开发工具安装、源码获取导入到调试配置&#x…

    Dify,FastGPT,RagFlow有啥区别,在智能问答方面有啥区别

    Dify、FastGPT、RagFlow都是当前非常流行的低代码AI应用开发平台&#xff0c;它们都专注于让用户能够快速构建AI应用&#xff0c;但在设计理念、功能特色和适用场景上有明显区别。 让我详细对比一下这三个平台&#xff1a; 1. 平台定位对比 Dify 定位&#xff1a;全栈AI应用…

    基站定位接口如何如何用PHP实现调用?

    随着“新基建”战略的推进&#xff0c;我国移动通信基站数量快速增长。截至2024年底&#xff0c;全国基站总数已达1265万个&#xff0c;其中5G基站超425万个&#xff0c;构建起全球规模最大、技术领先的通信网络。 在这一基础上&#xff0c;基站查询API通过整合三大运营商数据…

    Day 4:Shell流程控制——从“直线思维“到“智能决策“的进化

    目录 一、if语句&#xff1a;你以为简单其实暗藏杀机1. 基础语法&#xff08;看似简单却容易踩坑&#xff09;2. 安全写法规范&#xff08;企业级建议&#xff09; 二、条件测试的六大门派1. 文件测试&#xff08;运维最爱&#xff09;2. 字符串比较&#xff08;引号是灵魂&…

    分布式训练中的随机种子策略:深入理解与实践指南

    分布式训练中的随机种子策略&#xff1a;深入理解与实践指南 引言&#xff1a;一个容易被忽视的关键细节 在深度学习的分布式训练中&#xff0c;你是否见过这样的代码&#xff1f; torch.manual_seed(process_seed) # PyTorch操作 random.seed(process_seed) # Pyth…

    金山办公发布WPS智慧教育平台,发力教育AI意义何在?

    钛媒体消息&#xff0c;金山办公发布面向教育用户的 WPS 智慧教育平台&#xff0c;面对着金山办公的发力&#xff0c;我们该怎么分析呢&#xff1f; 首先&#xff0c;从市场拓展与用户需求响应角度看&#xff0c;金山办公此次推出WPS智慧教育平台&#xff0c;直接瞄准了教育领…

    无人机航电系统之语音通信技术篇

    无人机航电系统的语音通信技术是确保无人机与地面控制站、其他无人机或相关人员之间实现高效、稳定语音交互的关键技术&#xff0c;在军事侦察、应急救援、物流运输、航拍测绘等众多领域发挥着至关重要的作用。 一、技术原理 无人机航电系统的语音通信技术主要基于无线通信原理…

    element plus 的树形控件,如何根据后台返回的节点key数组,获取节点key对应的node节点

    在使用 Element Plus 的 el-tree 组件时&#xff0c;如果后端返回的节点 key 数组中包含了部分选中的父级节点的 key&#xff0c;可能会导致该父级节点下的所有子节点也被默认选中。这是因为 el-tree 的默认行为是&#xff1a;如果一个父节点被选中&#xff0c;那么其所有子节点…

    什么是Sentinel

    什么是 Sentinel? 在分布式系统中,服务间的依赖关系错综复杂。一个服务的故障,很可能像多米诺骨牌一样,迅速蔓延并导致整个系统崩溃,这就是我们常说的“雪崩效应”。为了避免这种灾难性后果,我们需要一种强大的机制来保护我们的系统,而 Sentinel 正是为此而生。 Senti…

    AWS 使用图形化界面创建 EKS 集群(零基础教程)

    无需命令行&#xff01;通过 AWS 控制台图形化操作&#xff0c;轻松创建 Kubernetes 集群。 文章目录 文章简介 一、准备工作&#xff1a;登录 AWS 控制台 二、创建 EKS 集群&#xff08;控制面&#xff09; 1. 创建 EKS 集群 2. 设置集群基本信息 3. 配置网络设置 三、添加…

    [C#] Winform - 进程间通信(SendMessage篇)

    一、发送端 // 窗体&#xff1a;发送端 public partial class SendForm : Form {public SendForm(){InitializeComponent();}// 按钮&#xff1a;发送private void btnSend_Click(object sender, System.EventArgs e){IntPtr hwnd User32Helper.FindWindow(null, "接收端…

    锂电池保护板测试仪:守护电池安全的幕后保障

    在电动汽车、储能电站和便携式电子设备中&#xff0c;锂电池作为核心动力源&#xff0c;其能量密度与安全性始终是行业关注的焦点。锂电池在过充、过放、短路等异常情况下可能引发起火甚至爆炸&#xff0c;而锂电池保护板正是解决这一问题的关键组件。为确保保护板性能可靠&…

    Qemu搭建RISC-V,运行opensbi+u-boot+img

    ✨1.先下载一个Ubuntu镜像 https://cdimage.ubuntu.com/releases/24.04/release/ 我这里下载的是这个RISC-V的 &#x1f31f;1.2.解压镜像 xz -d ubuntu-24.04.2-preinstalled-server-riscv64.img.xz ✨2.准备RISC-V的QEMU 打开qemu官网https://www.qemu.org/&#xff0c…

    【实战手册】银河麒麟服务器系统进入单用户模式修改密码(root)指南

    目录 前言 一、银河麒麟单用户模式简介 二、进入单用户模式修改密码 三、登录验证新密码 结语 前言 在日常服务器运维工作中&#xff0c;忘记root密码是系统管理员偶尔会遇到的问题。作为国产操作系统的优秀代表&#xff0c;银河麒麟服务器系统提供了通过单用户模式重置r…

    偏微分方程通解求解2

    题目 求下列方程的通解: { u x y = u x u y u − 1 ; u x y = u x u y ; u x y = u x u y u u 2 + 1 ; \begin{cases} u_{xy} = u_x u_y u^{-1}; \\ u_{xy} = u_x u_y; \\ u_{xy} = \dfrac{u_x u_y u}{u^2 + 1}; \end{cases} ⎩⎪⎪⎨⎪⎪⎧​uxy​=ux​uy​u−1;uxy​=ux​…

    用于算法性能预测的 GNN 框架

    大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象。 数值黑盒优化中的自动算法性能预测通常依赖于问题特征&#xff0c;例如探索性景观分析特征。这些特征通常用作机器学习模型的输入&#xff0c;并以表格格式表示。然而&#xff0c;这种方法往往忽…

    拯救海量数据:PostgreSQL分区表性能优化实战手册(附压测对比)

    1 分区表核心原理与生产痛点 物理存储结构决定性能边界 PostgreSQL分区表的本质是继承表路由规则的逻辑封装。当父表被查询时&#xff0c;查询优化器通过CHECK约束快速定位子表&#xff0c;其性能核心取决于&#xff1a; -- 关键系统视图 SELECT relname, relkind, relpages …

    【Wi-Fi天气时钟】网络授时

    文章目录 1 网络授时概述1.1 什么是网络授时1.2 为什么要使用网络授时2 API概述2.1 什么是API2.2 如何使用API3 淘宝时间API简介4 网络授时流程和AT指令5 网络授时程序设计5.1 API返回信息解析5.2 RTC初始化5.3 必要的后续操作6 结语1 网络授时概述 1.1 什么是网络授时 首先我…

    腾讯云IM即时通讯:开启实时通信新时代

    一、引言 在当今数字化浪潮席卷全球的时代&#xff0c;即时通讯已然成为互联网世界中不可或缺的关键元素。无论是个人日常生活中的社交互动&#xff0c;还是企业运营里的高效协作&#xff0c;即时通讯都发挥着举足轻重的作用&#xff0c;已然渗透到人们生活与工作的每一个角落…