初识Qt Quick

news2025/7/12 7:33:09

讲讲最近几年Qt的热门技术Quick这一块了。

啥是Qt?

哦,这是一个宣称可以跨任意平台,开发各种场景应用软件的开发框架。从三个维度来讲,就是开发库framework,集成开发平台IDE,以及成熟的开发思维模式。

Qt Quick最早出现在Qt的4.7版本中,目标是在UI设计者与开发者之间搭建一个更高效合作平台,给开发者更好的UI开发体验。虽然几经易手,Qt在digia公司这些年的努力迭代更新下,Qt Quick终于迎来了成熟稳定的版本(这也是我愿意在最近的项目里转用它的原因)。

至于Qt Quick和老一套开发核心Qwidget的区别,其中最重点的就是提供了新的UI描述语言QML(Qt Meta-object Language,Qt元对象描述语言)。QML乍看起来有点像json,但是核心思想却是模仿web页面。没错,在QML文件中允许搭配Javascript代码,就可以辅助实现丰富的UI交互逻辑。

如果你以往习惯QWidget开发,那么Qt Quick真的非常值得上手试试。

好了,口水吐多了招人厌,下面直入庐山一窥真面目!

手剥一个简单的功能程序开发栗子

在Qt开发过程中,Qt官方IDE(Qt Creator)提供了好几种工程构建工具,比如简单易懂的qmake,火上天的cmake,还有貌似没人听说过的Qbs。而目前Qt主推的构建方式就是cmake,下面要讲的例子也是用cmake。

1.开发环境配置

Win10
Qt 6.2.4
Qt Creator 8.0.1
Mingw 11.2.0 64bit
Cmake 3.23.2

这里选用的Qt版本是写作时最新的LTS版本,LTS意思就是官方长期支持更新。比如说,一两年内还会发布一下补丁和安全更新,至于新功能特性就别想了。

2.创建Qt Quick工程

先用Qt Creator创建一个简单的quick工程,工程构建描述的内容就保存在工程根目录的配置文件CMakeLists.txt中,如下:

cmake_minimum_required(VERSION 3.16)

project(instance VERSION 0.1 LANGUAGES CXX)

set(CMAKE_AUTOMOC ON)
#set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Qt6 6.2 COMPONENTS Quick REQUIRED)

file(GLOB_RECURSE SOURCE_FILES
    ./src/*.cpp
    ./src/*.h
)

qt_add_resources(SOURCE_FILES instance.qrc)

qt_add_executable(instance
    ${SOURCE_FILES}
)

set_target_properties(instance PROPERTIES
    MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
    MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
    MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
    MACOSX_BUNDLE TRUE
    WIN32_EXECUTABLE TRUE
)

target_link_libraries(instance
    PRIVATE Qt6::Quick)

install(TARGETS instance
    BUNDLE DESTINATION .
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QT嵌入式开发,Quick模块等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

cmake_minimum_required用于声明当前的配置文件适用于的cmake最低版本,同时为了防止使用过于低级的版本来构建当前工程,避免某些指令不支持或者不兼容。

project用于声明当前工程名称,和开发语言。CXX代表了C++。

CMAKE_AUTOMOC用于标记是否开启自动MOC。Qt不仅仅是开发库,它同时也对开发语言(比如C++)做了拓展,那么源码文件中就会多多少少会包含有通用编译器无法识别的部分内容。MOC就是用于对Qt的扩展内容进行转换的工具。

CMAKE_AUTORCC用于标记是否开启自动RCC。在Qt工程中会包含有被最终输出的执行程序所需要的资源内容,比如音视频,图片等等。那么为了高效调用这些资源,势必需要对原本的资源文件进行处理再保存到额外的二进制文件中,甚至内嵌到执行文件中。RCC就是对这些资源文件进行处理和再输出工具。

由于我的例子工程中需要用到MOC和RCC,所以CMAKE_AUTOMOC和CMAKE_AUTORCC都打开。

CMAKE_AUTOUIC用于标记是否开启自动UIC。如果开发界面用的技术栈是QWidget,那么在Qt工程中就需要创建.ui文件并保存设计内容到其中,编译的时候也需要用UIC把.ui文件转换成.h文件。不过,这里用Quick技术栈开发界面,因此无需打开CMAKE_AUTOUIC,在最前面添加#表示注释掉该行语句(该行语句会被解析器忽略)。

用find_package导入Qt的Quick模块。

由于本工程需要用到多个C++源文件,所以这里采用了递归引用文件的方式把特定文件夹下面的所有.cpp、.h等文件都囊括进来,需要辅以通配符*。所有被囊括的文件路径被追加到动态数组SOURCE_FILES中,方便后边引用。语法格式如下:

file(GLOB_RECURSE <variable> [FOLLOW_SYMLINKS]
     [LIST_DIRECTORIES true|false] [RELATIVE <path>]
     [<globbing-expressions>...])

格式里的variable实际使用SOURCE_FILES代替。

qt_add_resources的作用是调用RCC对资源文件(.qrc)编译成qrc_开头的源文件再输出,并且把输出的源码文件路径追加到动态数组SOURCE_FILES中。

当然,动态数组SOURCE_FILES这个名字可以按照需求自定义设定,这里取名为源文件。

qt_add_executable指明构建的目标是二进制文件instance,引用的源文件来自于动态数组SOURCE_FILES。

target_link_libraries用于指明构建时链接Qt6::Quick的相关库。

剩余的语句都是Qt Creator创建工程时自动添加的内容,这里略过。

然后看看我的工程目录结构在Qt Creator中的展示:

 

如果用VSCODE打开工程目录,可以看到:

 

3.使用元对象描述文件(QML)描述界面

使用Qt Creator自动创建的Quick应用,除了会自动生成配置文件CMakeLists.txt之外,还包含了main.cpp和main.qml文件,源码只实现了启动之后弹出一个窗口。

这里稍作修改,实现简单的文件选择,以及将选中的文件路径名显示出来。这个功能用QWidget技术栈来实现其实是很简单的啦,不过我们这里目的是演示Quick技术框架怎么用,所以下面来具体看看界面这块怎么玩:

1)主页面

// main.qml

import QtQuick

Window {
    width: 640
    height: 200
    visible: true
    title: qsTr("Tool V1.0.0")
    Viewer {
        anchors.fill: parent
    }
}

main.qml 这个文件是首页元对象的描述文件,一般QML引擎加载的第一个元对象所在的文件就命名为main.qml。不过,命名为main.qml不是硬性规定。

首先,可以看到这里通过import导入了模块QtQuick。同一行,后边还可以加上版本号。

Window是一种模块里预定义的类型,用于窗体描述。当然,类型也可以自定义,下面会说到。这里通过对类型Window的实例化来描述一个窗体对象。

类型后边的{}内部包含了类型实例化后的成员属性、函数、信号、信号处理句柄等,比如width、height、visible、title等都是预定义的属性,这些属性如字面意思比较简单易懂就不一一展开了,大伙要是有兴趣可以反馈给我,我再看看意见给大家细聊。

Viewer其实是自定义的类型,这里通过对类型Viewer的实例化来补充添加新的界面元素。Viewer对象内部的属性anchors.fill: parent描述的是对象在其父对象(Window)中把父对象填充满。QML一般通过anchors属性来锚定对象的位置。

上面这个对象里并没有定义或者引用到函数或者信号等。

2)自定义类型

下面来看看怎么自定义类型

// Viewer.qml

import QtQuick 2.15
import QtQuick.Controls 6.2
import Qt.labs.platform 1.1

Item {
    function log(...msg) {
        let msgs = "";
        msg.forEach((item) => {
                        if (msgs.length != 0) {
                            msgs += " ";
                        }
                        msgs += item;
                    });
        console.log(msgs);
    }

    FileDialog {
        id: fileDialog
        objectName: "fileDialog"
        currentFile: selectedFileTextArea.text

        onFileChanged: {
            log(objectName + ".file =", file.toString().slice(8));
            fileMgrInstance.run(file.toString().slice(8));
        }
    }

    Label {
        id: fileLable
        x: 292
        y: 26
        text: qsTr("文件:")
        verticalAlignment: Text.AlignVCenter
        font.pointSize: 14
    }

    TextField {
        id: selectedFileTextArea
        x: 70
        y: 70
        width: 500
        objectName: "selectedFileTextArea"
        text: fileDialog.file.toString().slice(8)
        font.pointSize: 12
        placeholderText: qsTr("选择文件")
    }

    Button {
        id: selectFileButton
        x: 268
        y: 124
        width: 105
        height: 54
        text: qsTr("选择")
        font.pointSize: 10

        onClicked: {
            log(text, "clicked");
            fileDialog.open();
        }
    }
}

Item是类库QtQuick的预定义组件类型,描述的是一个基础可视组件,quick中所有的可视组件都继承于它。

一般在QML中自定义类型都会使用基础的类型Item,然后在其基础上定制内部属性、函数、信号、信号处理句柄等。

Item的继承链是这样的:

Item -> QtObject -> QObject

看到这里,可以猜测一下,其实所有的Quick预定义组件都是继承于QObject,和QWidget里提供的类库太相似了。

function log(...msg)定义了函数log,function是关键词,log是函数名,后边小括号里的...表示参数不定,这样子在调用log时就可以不限制输入的参数个数了。

要注意的是,QML内部的函数使用的语法是ECMAScript,也就是我们常常听到的JavaScript。

FileDialog是类库Qt.labs.platform的预定义组件类型,描述的是一个文件选择窗口。属性id,继承于QObject,用于标记唯一的对象,也就是说所有对象的id都不能重复,无论对象是否处于同一个QML文件。objectName描述的属性可用于对对象树中的对象进行查找。currentFile描述了当前选中的文件名(包括路径),在确定最后选中的文件之前,此属性也会跟随选择而改变。onFileChanged描述了当属性file值改变时,自动产生的信号的处理句柄(handle),用{}限定处理范围。log是上面定义的函数调用,输入两个参数。fileMgrInstance是C++源文件暴露给QML引擎的特定对象id,通过该id可以调用C++中的相应对象的方法属性(代码中调用了run方法,方法的详情定义看下文)。

C++和QML源文件之间的对象相互调用,会有后续的文章专门介绍,这里不再细聊,敬请关注。

Label是类库QtQuick.Controls的预定义组件类型,描述的是一个文本标签。x、y描述的是坐标。text描述的是显示文本。qsTr()用于标识文本可被翻译,类似Qt C++里的tr()。verticalAlignment描述的是垂直排列方式,这里的属性值标识垂直中间排列。font.pointSize描述字体的大小。

TextField是类库QtQuick.Controls的预定义组件类型,描述的是一个单行文本编辑窗。width是几何宽度。placeholderText描述的是占位符。

Button是类库QtQuick.Controls的预定义组件类型,描述的是一个可点击的按键。height描述的是几何高度。onClicked描述了当信号clicked发生时,该信号的处理句柄(handle),用{}限定处理范围,这里调用了上面的文件选择窗的打开函数。

信号的处理句柄(handle)中,在on后边书写时信号的首字母需要大写。

3)预览界面

什么?代码没写完就可以预览界面了?

是的,QML文件支持用工具预览,非常方便于UI设计过程中的调试。

打开预览的方式是调用qmlscene或者用Qt Design Studio,如下图用的是qmlscene。

 

看看Viewer.qml页面预览的实际效果。

 

4.使用C++代码实现逻辑处理

Qt Quick使用QML的目的是为了简化界面的设计开发,而软件除了界面的互动之外还有大量的后台逻辑处理功能也需要实现,针对这块业务,Qt其实还是推荐使用C++,正所谓术业有专攻,毕竟C++对性能的利用还是有两把刷子的。废话不多说,马上看下文。。。

既然如此,那么就来看看负责逻辑处理功能的C++代码部分。不过,这里假设各位看官已经熟悉C++的各项业务技能,所以下面只针对和QML对象的互动来简单介绍一下。

后续也会有更加详细的专题文章介绍这部分,敬请留意哈!

1)QML对象的加载和C++对象传递

QML对象的创建和展现是通过QML引擎来加载的,一般每个程序会由单个引擎对象负责管理。不过,QML引擎对象不是直接管理QML对象,而是通过管理上下文(context)对象来分别管理QML对象。所以在C++里边如果需要往QML对象传递信息也是直接传给对应的上下文对象,然后再在QML对象中通过传入对象时指定的id名调用对应的方法属性。

// main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "./FileMgr/FileMgr.h"

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

    QQmlApplicationEngine engine;
    const QUrl url(u"qrc:/src/QML/main.qml"_qs);
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        qInfo("%s start\n", QCoreApplication::applicationName().toLatin1().data());

        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);

    FileMgr fileMgr;
    engine.rootContext()->setContextProperty(QStringLiteral("fileMgrInstance"), &fileMgr);
    engine.load(url);

    return app.exec();
}

上面的main.cpp文件代码中,把对象fileMgr传入引擎的根上下文中,并设定id为fileMgrInstance。传入根上下文,意味着引擎加载的所有QML对象都可以通过id=fileMgrInstance访问fileMgr对象内容。这里要注意,fileMgr对象是在C++源码中实例化了的。

把C++对象暴露给QML对象的方法,除了上面这种通过上下文的方式外,还有一种是通过直接往元对象系统(Meta-Object System)注册类型的方式,这种方式也是最根本的方式,因为Qt Quick框架的底层实现原理就依赖于元对象系统。

使用的接口原型:

template <typename T> int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName)

如果通过这种注册的方式实现,上面的栗子可以掰成这样:

 qmlRegisterType<FileMgr>("com.englyf.qmlcomponents", 1, 0, "FileMgrItem");

根据上面的定义,com.englyf.qmlcomponents是命名空间,1.0是命名空间的版本号,FileMgrItem是QML中的类型名。

然后在QML文件内,导入并实例化这个类:

 import com.englyf.qmlcomponents 1.0

 FileMgrItem {
     // ...
 }

要强调的是,通过注册的方式,类型的实例化会放在QML里边做,而C++源码就不需要再对类FileMgr作实例化了

2)C++类型的定义

既然Qt Quick依赖于元对象系统,那么对C++类型的定义就有必然的要求了。

C++类型需要继承于QObject,并且类开头应该声明宏Q_OBJECT,这样才可以使用元对象系统提供的服务,包括信号槽机制等等。

需要被QML对象调用的方法应该添加修饰Q_INVOKABLE。这个修饰符表明该方法可被元对象系统调用。同时,该方法的参数类型和返回类型,都推荐使用类型QVariant。

如有开放给QML对象的可访问属性,那么也需要对属性声明为Q_PROPERTY。这里暂不举例,可关注后续的专题文章。

// FileMgr.h

#ifndef FILEMGR_H
#define FILEMGR_H

#include <QObject>
#include <QVariant>

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

    Q_INVOKABLE QVariant run(QVariant file);
};

#endif // FILEMGR_H

// FileMgr.cpp

#include "FileMgr.h"

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

QVariant FileMgr::run(QVariant file)
{
    QString fileStr = file.toString();
    qDebug("C++ get file:%s selected", fileStr.toStdString().data());

    return 0;
}

自动化部署

这部分讲点高级的内容,以往看到网上的教程都是教初学者部署的时候,进入exe生成的目录,然后手动调用windeployqt执行部署。这个程序是Qt自带的,会自动把所有依赖的动态库拷贝过来存放在指定目录下。

这里就介绍一下怎么在Qt Quick软件工程编译结束时自动部署所有依赖项。

首先,debug开发模式下是不需要部署软件的,那么我们就先切换到release模式下。

然后,在Build的步骤下,Build步骤之后新添加一个Custom Process Step的步骤。

 

我把配置都拷过来:

Command:            windeployqt
Arguments:          --qmldir %{ActiveProject:NativePath}\src\QML\ %{ActiveProject:RunConfig:Executable:NativeFilePath}
Working directory:  %{Qt:QT_INSTALL_BINS}

由于Qt Quick工程涉及到QML文件,所以这里需要带上选项--qmldir,这个选项后边紧跟着参数值是代码工程中存放自定义的QML文档的根目录。

%{ActiveProject:NativePath}代表着当前工程的主目录的本地化路径。

%{ActiveProject:RunConfig:Executable:NativeFilePath}代表着当前工程的exe文件输出目录的本地化路径。

Working directory项意思是Command命令的工作目录,这里填上%{Qt:QT_INSTALL_BINS},代表Qt安装目录下的bin目录。

按照上面的介绍过程配置完整,以后如果需要部署输出,只需要切换到release模式下,然后点击编译,等编译完成就会自动进入部署流程,整个过程就是这么舒心。

生活简单才是美好,部署也不例外!


到最后,一起来看看跑起来的程序:

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QT嵌入式开发,Quick模块等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

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

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

相关文章

CAS:82055-94-5,Azide-PEG-Azide,N3-PEG-N3,叠氮聚乙二醇叠氮试剂供应

1、名称 英文&#xff1a;Azide-PEG-Azide&#xff0c;N3-PEG-N3 中文&#xff1a;叠氮-聚乙二醇-叠氮 2、CAS编号&#xff1a;82055-94-5 3、所属分类&#xff1a;Azide PEG 4、分子量&#xff1a;可定制&#xff0c;叠氮-PEG-叠氮 2000、叠氮peg叠氮 1000、叠氮-聚乙二醇…

org.activiti.bpmn

org.activiti.bpmn目录概述需求&#xff1a;设计思路实现思路分析1.BpmnAutoLayout2.BPMNLayout参考资料和推荐阅读Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better result,wait for ch…

Mybatis概述

1 概述 原来是Apache的一个开源项目&#xff0c;叫iBatis, 2010年6月这个项目由 Apache Software Foundation 迁移到了 Google Code&#xff0c;随着开发团队转投Google Code 旗下&#xff0c;从 iBatis3.0正式更名为MyBatis。 MyBatis 是一款优秀的持久层框架&#xff0c;对j…

容器卷挂载的秘密

什么是容器卷 数据卷 &#xff08;Data Volumes &#xff09;是一个可供容器使用的特殊目录&#xff0c;它将主机操作系统目录直接映射进容器&#xff0c;类似于 Linux 中的 mount 行为。 容器挂载原理 containerd创建的容器里的数据存储在下面的目录中 [rootmaster01 httpb…

【C/C++】万字图文详解C语言文件操作 完美装饰课设大作业

目标导航 写在前面 为什么使用文件&#xff1f; 什么是文件&#xff1f; 程序文件 数据文件 认识文件名 文件的打开和关闭 文件指针 文件的打开和关闭 1.以"r"&#xff08;只读&#xff09;的方式打开文件 2.以"w"&#xff08;只写&#xff09;…

Java#24(常见API--2)

目录 一.Rantime Runtime表示当前虚拟机的运行环境 Runtime常用方法 扩展:对象克隆 二.Objects Objects是一个对象工具类,提供了一些操作对象的方法 一.Rantime Runtime表示当前虚拟机的运行环境 Runtime常用方法 方法名 作用 publi…

葡萄糖-聚乙二醇-链霉亲和素|Streptavidins-PEG-Glucose|链霉亲和素-PEG-葡萄糖

链霉亲和素(streptavidin下称SA)是与亲和素(avidin下称AV)是一种蛋白质&#xff0c;链霉亲和素是四聚体蛋白&#xff0c;大小为66KDa。一分子链霉亲和素可以高度特异性地与四分子生物素结合&#xff0c;两者之间的亲和力较为强烈。链霉亲和素分子由4条相同的肽链组成&#xff0…

delete-by-query和复合查询

根据term&#xff0c;match等查询方式去删除大量的文档 Ps&#xff1a;如果你需要删除的内容&#xff0c;是index下的大部分数据&#xff0c;推荐创建一个全新的index&#xff0c;将保留的文档内容&#xff0c;添加到全新的索引 # delete-by-query POST /sms-logs-index/sms-lo…

毕业设计-基于机器视觉的颜色目标识别

目录 前言 课题背景和意义 实现技术思路 什么是彩色空间 怎么利用彩色空间 颜色识别的过程 读取图片进行hsv色域转换 对图片特定颜色识别 本地摄像头对视频流进行颜色识别 实现效果图样例 前言 &#x1f4c5;大四是整个大学期间最忙碌的时光,一边要忙着备考或实习为毕业后…

Python基础-面向对象编程之特性(property)

Python面向对象编程之特性(property) 一、统一访问原则 通常&#xff0c;我们访问实例或类的属性时&#xff0c;将返回所存储的相关值。而特性&#xff08;property&#xff09;是一种特殊的属性&#xff0c;访问它时会计算它的值。 请看下面的例子&#xff1a; import mat…

基于android的个性闹铃的设计与开发(闹铃,日历,计时器,备忘录)

目 录 摘 要 2 Abstract 2 1 选题的背景和意义 5 1.1 选题的背景 5 1.2 国内外研究现状 5 1.2.1 国内外手机系统现状 5 1.2.2 国内外手机应用现状 7 1.2.3 发展趋势 7 2 需求分析 9 2.1 系统需求 9 2.2 需求分析 9 2.3 约束与限制 10 3 总体设计 11 3.1 系统结构图 11 3.2 总体…

【数论】约数

文章目录一、试除法求n的所有约数二、约数个数三、约数之和四、最大公约数&#xff08;欧几里得算法/辗转相除法&#xff09;一、试除法求n的所有约数 vector<int> getDivisors(int n) {vector<int> ans;for (int i 2; i < n / i; i) {if (n % i 0) {ans.pus…

深度学习Week8-咖啡豆识别(Pytorch)

目录 一、前期准备 1.设置GPU 2. 导入数据 3. 划分数据集 二、手动搭建VGG-16模型 1. 搭建模型​编辑 2. 查看模型详情 三、 训练模型 1. 编写训练函数 2. 编写测试函数 4. 正式训练 四、 结果可视化 1. Loss与Accuracy图 2. 指定图片进行预测 3. 模型评估 *五、优…

[附源码]java毕业设计中达小区物业管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

学生家乡网页设计作品静态HTML网页模板源码 广西旅游景点网页设计 大学生家乡主题网站制作 简单家乡介绍网页设计成品

家乡旅游景点网页作业制作 网页代码运用了DIV盒子的使用方法&#xff0c;如盒子的嵌套、浮动、margin、border、background等属性的使用&#xff0c;外部大盒子设定居中&#xff0c;内部左中右布局&#xff0c;下方横向浮动排列&#xff0c;大学学习的前端知识点和布局方式都有…

Packet Tracer - 配置 IPv4 和 IPv6 接口

地址分配表 设备 接口 IPv4 地址 子网掩码 默认网关 IPv6 地址/前缀 R1 G0/0 172.16.20.1 255.255.255.128 不适用 G0/1 172.16.20.129 255.255.255.128 不适用 S0/0/0 209.165.200.225 255.255.255.252 不适用 PC1 NIC 172.16.20.10 255.255.255.128 1…

微服务架构的环境搭建及简单测试

目录 一、系统架构的演变过程 1.0 前言 1.1 单体应用架构 1.2 垂直应用架构 1.3 分布式架构 1.4 SOA架构 1.5 微服务架构 二、微服务架构搭建 2.1 微服务架构简介 2.2 微服务案例准备 2.3 创建父工程、基础模块 2.4 创建微服务 一、系统架构的演变过程 1.0 前言 随着互联网的…

【Queue】- 从源码分析PriorityQueue及其常用方法

文章目录PriorityQueue基础知识概述PriorityQueue内部结构PriorityQueue扩容操作PriorityQueue队列的构造方法PriorityQueue队列的常用方法public boolean offer(E e)public E peek()public boolean remove(Object o)public boolean contains(Object o)public Object[] toArray…

【SU-03T离线语音模块】:学习配置使用

前言 时不可以苟遇&#xff0c;道不可以虚行。 一、介绍 1、什么是语音识别模块 语音识别模块是在一种基于嵌入式的语音识别技术的模块&#xff0c;主要包括语音识别芯片和一些其他的附属电路&#xff0c;能够方便的与主控芯片进行通讯&#xff0c;开发者可以方便的将该模块嵌…

Node.js 入门教程 3 如何安装 Node.js

Node.js 入门教程 Node.js官方入门教程 Node.js中文网 本文仅用于学习记录&#xff0c;不存在任何商业用途&#xff0c;如侵删 文章目录Node.js 入门教程3 如何安装 Node.js3 如何安装 Node.js Node.js 可以通过多种方式安装。 所有主流平台的官方软件包都可以在 http://node…