【unity进阶知识6】Resources的使用,如何封装一个Resources资源管理器

文章目录

  • 一、Unity资源加载的几种方式
    • 1、Inspector窗口拖拽
    • 2、Resources
    • 3、AssetBundle
    • 4、Addressables(可寻址资源系统)
    • 5、AssetDatabase
  • 二、准备
  • 三、同步加载Resources资源
    • 1、Resources.Load同步加载单个资源
      • 1.1、基本加载
      • 1.2、加载指定类型的资源
      • 1.3、使用泛型加载指定类型的资源
    • 2、Resources.LoadAll同步加载多个资源
      • 2.1、基本加载
      • 2.2、加载指定类型的资源
      • 2.3、使用泛型加载指定类型的资源
  • 四、异步加载Resources文件夹中的资源
  • 五、封装一个Resources资源管理器
    • 1、封装异步加载资源
    • 2、封装同步加载资源
    • 3、封装卸载资源方法
  • 六、最终代码
  • 完结

一、Unity资源加载的几种方式

1、Inspector窗口拖拽

  • 在脚本中用public声明变量,然后在Inspector窗口把要加载的资源拖拽给该脚本的变量。
  • 不建议在大型项目使用。在公司的项目也不要用。如果你是独立游戏开发者,则可以用。
  • 不支持热更新。

2、Resources

  • 用Resources.Load方法、Resources.LoadAsync方法、Resources.LoadAll方法来加载资源。
  • 可以在商业项目使用,包括公司的项目。但是Resources文件夹中可以存放的资源有限,大概只能存储2G左右的资源,因此要谨慎使用。
  • 不支持热更新。

3、AssetBundle

  • 用AssetBundle.LoadFromXXX方法来加载资源。
  • 商业项目常用的资源加载方案,如果你在公司做项目,则推荐用这种方式来加载资源。
  • 效率比Resources加载高,占用内存小,正式发布游戏后,资源所占用的空间也小。
  • 支持热更新。

4、Addressables(可寻址资源系统)

  • 可以理解为高级的AssetBundle,资源管理由Unity内部自动完成。
  • 但是目前还在发展中,可能有bug。主流的商业游戏都是使用AssetBundle来做资源加载的。
  • 支持热更新。

5、AssetDatabase

  • 用AssetDatabase.LoadAssetAtPath方法来加载资源。
  • 仅限于编辑器模式,主要用于在编辑器模式下用代码更改本地文件。
  • 游戏运行时不会用这种方案加载资源。
  • 不支持热更新。

二、准备

使用前必须在项目中创建一个名叫Resources的文件夹,这个名字是固定的。
在这里插入图片描述

三、同步加载Resources资源

1、Resources.Load同步加载单个资源

1.1、基本加载

Resources.Load(string 要加载的资源的路径)

返回值是Object型。

如果有多个相同路径的资源,则只会返回找到的第一个资源。

调用案例

GameObject go = Resources.Load("Prefabs/Cube") as GameObject;

1.2、加载指定类型的资源

Resources.Load(string 要加载的资源的路径, System.Type 要加载的资源的类型的Type对象)

返回值是Object型。

如果有多个相同类型且相同路径的资源,则只会返回找到的第一个资源。

调用案例

GameObject go = Resources.Load("Prefabs/Cube", typeof(GameObject)) as GameObject;

1.3、使用泛型加载指定类型的资源

Resources.Load<要加载的资源的类型>(string 要加载的资源的路径)

返回值是T型。

返回值是要加载的资源的类型。如果有多个相同类型,且相同路径的资源,则只会返回找到的第一个资源。

调用案例

GameObject go = Resources.Load<GameObject>("Prefabs/Cube");

2、Resources.LoadAll同步加载多个资源

2.1、基本加载

Resources.LoadAll(string 要加载的资源的文件夹路径或文件路径)

返回值是Object[]型。

同步加载Resources文件夹中指定路径的文件夹中的所有资源,包括其中子孙文件夹中的所有资源,然后返回到一个Object[]型数组。

如果该路径是一个文件,则只会加载该文件,并返回到一个Object[]型数组。如果没有加载到任何资源,则返回一个没有任何元素的Object[]型数组。

调用案例

Object[] gos = Resources.LoadAll("Prefabs");
for (int i = 0; i < gos.Length; i++)
{Instantiate(gos[i] as GameObject);
}

2.2、加载指定类型的资源

Resources.LoadAll(string 要加载的资源的文件夹路径或文件路径,System.Type 要加载的资源的类型的Type对象)

返回值是Object[]型。

同步加载Resources文件夹中指定路径的文件夹中的指定类型的所有资源,包括其中子孙文件夹中的该类型的所有资源,然后返回到一个Object[]型数组。

如果该路径是一个该指定类型的文件,则只会加载该文件,并返回到一个Object[]型数组。如果没有加载到任何资源,则返回一个没有任何元素的Object[]型数组。

调用案例

Object[] gos = Resources.LoadAll("Prefabs", typeof(GameObject));
for (int i = 0; i < gos.Length; i++)
{Instantiate(gos[i] as GameObject);
}

2.3、使用泛型加载指定类型的资源

Resources.LoadAll<泛型T类型>(string 要加载的资源的文件夹路径或文件路径)

返回值是T[]型。

同步加载Resources文件夹中指定路径的文件夹中的指定类型的所有资源,包括其中子孙文件夹中的该类型的所有资源,然后返回到一个T[]型数组。

如果该路径是一个该指定类型的文件,则只会加载该文件,并返回到一个T[]型数组。如果没有加载到任何资源,则返回一个没有任何元素的T[]型数组。

调用案例

GameObject[] gos = Resources.LoadAll<GameObject>("Prefabs");
for (int i = 0; i < gos.Length; i++)
{Instantiate(gos[i]);
}

四、异步加载Resources文件夹中的资源

Resources.LoadAsync异步加载单个资源方法

使用泛型加载指定类型的资源

Resources.LoadAsync<泛型T类型>(string 要加载的资源的路径)

返回值是ResourceRequest类型。

一般配合协程来使用。在协程中可以使用yield return来等待资源加载。

如果有多个相同路径的资源,则只会加载找到的第一个资源。

调用案例

void Start()
{StartCoroutine(LoadAsyncCoroutine());
}IEnumerator LoadAsyncCoroutine(){//开始异步加载资源ResourceRequest rr = Resources.LoadAsync<GameObject>("Prefabs/Cube");//等待资源加载完毕yield return rr;//加载完成执行逻辑Instantiate(rr.asset);
}

五、封装一个Resources资源管理器

1、封装异步加载资源

注意这个脚本依赖Mono管理器:【unity进阶知识2】Mono管理器

public class ResourcesManager : Singleton<ResourcesManager>
{/// <summary>/// 异步加载Resources文件夹中指定类型的资源/// </summary>public void LoadAsync<T>(string path, UnityAction<T> callback = null) where T : Object{MonoManager.Instance.StartCoroutine(LoadAsyncCoroutine(path, callback));}IEnumerator LoadAsyncCoroutine<T>(string path, UnityAction<T> callback = null) where T : Object{ResourceRequest resourceRequest = Resources.LoadAsync<T>(path);yield return resourceRequest;callback?.Invoke(resourceRequest.asset as T);}
}

调用,效果和前面一样

ResourcesManager.Instance.LoadAsync<GameObject>("Prefabs/Cube", Callback);void Callback(GameObject obj){Instantiate(obj);
}

或者

ResourcesManager.Instance.LoadAsync<GameObject>("Prefabs/Cube", (obj)=>{Instantiate(obj);
});

2、封装同步加载资源

同步加载封装虽然是一样的,但是好处是自己封装可以统一管理和进行自定义注释

/// <summary>
/// <para>同步加载Resources文件夹中指定类型的资源。</para>
/// <para>如果有多个相同类型,且相同路径的资源,则只会返回找到的第一个资源。</para>
/// </summary>
/// <typeparam name="T">要加载的资源的类型</typeparam>
/// <param name="path">要加载的资源的路径。例如"Prefabs/Cube"表示Resources文件夹中的Prefabs文件夹中的名叫Cube的资源。</param>
public T Load<T>(string path) where T : Object
{return Resources.Load<T>(path);
}

调用

GameObject[] gos = ResourcesManager.Instance.LoadAll<GameObject>("Prefabs");
for (int i = 0; i < gos.Length; i++)
{Instantiate(gos[i]);
}

3、封装卸载资源方法

通过Resources加载的资源,就算销毁了,但是它还是占在内存里面,没有释放,所以我们需要卸载资源,比如切换场景的时候

/// <summary>
/// <para>异步卸载所有用Resources方式加载到内存中且当前没有被任何地方使用的资源。</para>
/// <para>例如要卸载某一个用Resources方式加载的预制体,则必须确保场景中所有这个预制体创建的物体都被销毁了,且这个预制体资源没有赋值给任何脚本中的任何变量。</para>
/// <para>如果有,可以把该变量也赋值为null,这样本方法才能成功释放它。</para>
/// </summary>
/// <param name="callback">资源卸载完毕后执行的逻辑</param>
public void UnloadUnusedAssets(UnityAction callback = null)
{MonoManager.Instance.StartCoroutine(UnLoadUnusedAssetsCoroutine(callback));
}
IEnumerator UnLoadUnusedAssetsCoroutine(UnityAction callback = null)
{//异步操作对象,记录了异步操作的数据。AsyncOperation asyncOperation = Resources.UnloadUnusedAssets();//等待资源卸载while (asyncOperation.progress < 1)yield return null;//资源卸载完毕后执行的逻辑callback?.Invoke();
}

调用

ResourcesManager.Instance.UnloadUnusedAssets(() =>
{Debug.Log("异步卸载所有资源成功");
});

六、最终代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using XYFrame;/// <summary>
/// Resources资源加载管理器
/// 这个脚本依赖Mono管理器。
/// 要加载的资源必须放到项目中名叫Resources的文件夹中。项目中可以有多个名叫Resources的文件夹,但如此一来,必须避免资源的路径相同。
/// </summary>
public class ResourcesManager : Singleton<ResourcesManager>
{#region 同步加载单个资源/// <summary>/// <para>同步加载Resources文件夹中的资源。</para>/// <para>如果有多个相同路径的资源,则只会返回找到的第一个资源。</para>/// </summary>/// <param name="path">要加载的资源的路径。例如"Prefabs/Cube"表示Resources文件夹中的Prefabs文件夹中的名叫Cube的资源。</param>public Object Load(string path){return Resources.Load(path);}/// <summary>/// <para>同步加载Resources文件夹中指定类型的资源。</para>/// <para>如果有多个相同类型,且相同路径的资源,则只会返回找到的第一个资源。</para>/// </summary>/// <param name="path">要加载的资源的路径。例如"Prefabs/Cube"表示Resources文件夹中的Prefabs文件夹中的名叫Cube的资源。</param>/// <param name="systemTypeInstance">要加载的资源的类型的Type对象。例如typeof(GameObject)表示要加载的资源的类型是GameObject型。</param>/// <returns></returns>public Object Load(string path, System.Type systemTypeInstance){return Resources.Load(path, systemTypeInstance);}/// <summary>/// <para>同步加载Resources文件夹中指定类型的资源。</para>/// <para>如果有多个相同类型,且相同路径的资源,则只会返回找到的第一个资源。</para>/// </summary>/// <typeparam name="T">要加载的资源的类型</typeparam>/// <param name="path">要加载的资源的路径。例如"Prefabs/Cube"表示Resources文件夹中的Prefabs文件夹中的名叫Cube的资源。</param>public T Load<T>(string path) where T : Object{return Resources.Load<T>(path);}#endregion#region 同步加载多个资源/// <summary>/// <para>同步加载Resources文件夹中指定路径的文件夹中的所有资源,包括其中子孙文件夹中的所有资源,然后返回到一个Object[]型数组。</para>/// <para>如果该路径是一个文件,则只会加载该文件,并返回到一个Object[]型数组。</para>/// <para>如果没有加载到任何资源,则返回一个没有任何元素的Object[]型数组。</para>/// </summary>/// <param name="path">要加载的文件夹或文件的路径。例如"Prefabs"表示Resources文件夹中的Prefabs文件夹。例如"Prefabs/Cube"表示Resources文件夹中的Prefabs文件夹中的名叫Cube的资源。</param>public Object[] LoadAll(string path){return Resources.LoadAll(path);}/// <summary>/// <para>同步加载Resources文件夹中指定路径的文件夹中指定类型的所有资源,包括其中子孙文件夹中的该类型的所有资源,然后返回到一个Object[]型数组。</para>/// <para>如果该路径是一个该指定类型的文件,则只会加载该文件,并返回到一个Object[]型数组。</para>/// <para>如果没有加载到任何资源,则返回一个没有任何元素的Object[]型数组。</para>/// </summary>/// <param name="path">要加载的文件夹或文件的路径。例如"Prefabs"表示Resources文件夹中的Prefabs文件夹。例如"Prefabs/Cube"表示Resources文件夹中的Prefabs文件夹中的名叫Cube的资源。</param>/// <param name="systemTypeInstance">要加载的资源的类型的Type对象。例如typeof(GameObject)表示要加载的资源的类型是GameObject型。</param>public Object[] LoadAll(string path, System.Type systemTypeInstance){return Resources.LoadAll(path, systemTypeInstance);}/// <summary>/// <para>同步加载Resources文件夹中指定路径的文件夹中指定类型的所有资源,包括其中子孙文件夹中的该类型的所有资源,然后返回到一个Object[]型数组。</para>/// <para>如果该路径是一个该指定类型的文件,则只会加载该文件,并返回到一个Object[]型数组。</para>/// <para>如果没有加载到任何资源,则返回一个没有任何元素的Object[]型数组。</para>/// </summary>/// <typeparam name="T">要加载的资源的类型</typeparam>/// <param name="path">要加载的文件夹或文件的路径。例如"Prefabs"表示Resources文件夹中的Prefabs文件夹。例如"Prefabs/Cube"表示Resources文件夹中的Prefabs文件夹中的名叫Cube的资源。</param>public T[] LoadAll<T>(string path) where T : Object{return Resources.LoadAll<T>(path);}/// <summary>/// <para>同步把Resources文件夹中指定路径的文件夹及其所有子孙文件夹中所有指定类型的资源添加到一个新建的字典中,并返回该字典。</para>/// <para>应保证Prefabs文件夹中以及它的子孙文件夹中没有重名的资源,如果有重名的,则只会添加找到的第一个资源进字典,其它重名的资源不会进到字典中。</para>/// </summary>/// <typeparam name="T">要加载的资源类型</typeparam>/// <param name="path">资源的路径。例如"Folder/Res"表示Resources文件夹中的Folder文件夹中的Res文件夹</param>public Dictionary<string, T> LoadAllIntoDictionary<T>(string path) where T : Object{Dictionary<string, T> dic = new Dictionary<string, T>();T[] temp = Resources.LoadAll<T>(path);for (int i = 0; i < temp.Length; i++){if (!dic.ContainsKey(temp[i].name))//字典不存在该键,才添加进去。这样可以防止字典的键名重复而报错。{dic.Add(temp[i].name, temp[i]);}else//如果字典已经存在该键,则跳过这个资源,并输出警告,不将它加入到字典中{Debug.LogWarning(string.Format("Resources/{0}的子孙文件夹的资源{1}与已经添加到字典中的资源重名,因此无法将它添加到字典中,请确保加载的资源的名字是唯一的。", path, temp[i].name));}}return dic;}/// <summary>/// <para>同步把Resources文件夹中指定路径及其所有子孙文件夹中所有指定类型的资源添加到指定的字典中</para>/// </summary>/// <typeparam name="T">要加载的资源类型</typeparam>/// <param name="path">资源的路径。例如"Folder/Res"表示Resources文件夹中的Folder文件夹中的Res文件夹</param>/// <param name="dictionary">指定的字典</param>public void LoadAllIntoDictionary<T>(string path, Dictionary<string, T> dictionary) where T : Object{T[] temp = Resources.LoadAll<T>(path);for (int i = 0; i < temp.Length; i++){if (!dictionary.ContainsKey(temp[i].name))//字典不存在该键,才添加进去。这样可以防止字典的键名重复而报错。{dictionary.Add(temp[i].name, temp[i]);}else//如果字典已经存在该键,则跳过这个资源,并输出警告,不将它加入到字典中{Debug.LogWarning(string.Format("Resources/{0}的子孙文件夹的资源{1}与已经添加到字典中的资源重名,因此无法将它添加到字典中,请确保加载的资源的名字是唯一的,并且传入参数的字典中不包含该名字的资源。", path, temp[i].name));}}}#endregion#region 异步加载单个资源/// <summary>/// <para>异步加载Resources文件夹中的资源。</para>/// <para>如果有多个相同路径的资源,则只会加载找到的第一个资源。</para>/// </summary>/// <param name="path">要加载的资源的路径。例如"Prefabs/Cube"表示Resources文件夹中的Prefabs文件夹中的名叫Cube的资源。</param>/// <param name="callback">资源加载完毕后要执行的逻辑。参数表示加载的资源。</param>public void LoadAsync(string path, UnityAction<Object> callback = null){MonoManager.Instance.StartCoroutine(LoadAsyncCoroutine(path, callback));}IEnumerator LoadAsyncCoroutine(string path, UnityAction<Object> callback = null){ResourceRequest resourceRequest = Resources.LoadAsync(path);yield return resourceRequest;callback?.Invoke(resourceRequest.asset);}/// <summary>/// <para>异步加载Resources文件夹中指定类型的资源。</para>/// <para>如果有多个相同类型,且相同路径的资源,则只会加载找到的第一个资源。</para>/// </summary>/// <param name="path"></param>/// <param name="type">要加载的资源的类型的Type对象。例如typeof(GameObject)表示要加载的资源的类型是GameObject型。</param>/// <param name="callback">资源加载完毕后要执行的逻辑。参数表示加载的资源。</param>public void LoadAsync(string path, System.Type type, UnityAction<Object> callback = null){MonoManager.Instance.StartCoroutine(LoadAsyncCoroutine(path, type, callback));}IEnumerator LoadAsyncCoroutine(string path, System.Type type, UnityAction<Object> callback = null){ResourceRequest resourceRequest = Resources.LoadAsync(path, type);yield return resourceRequest;callback?.Invoke(resourceRequest.asset);}/// <summary>/// <para>异步加载Resources文件夹中指定类型的资源。</para>/// <para>如果有多个相同类型,且相同路径的资源,则只会加载找到的第一个资源。</para>/// </summary>/// <typeparam name="T">加载的资源的类型</typeparam>/// <param name="path">要加载的资源的路径。例如"Prefabs/Cube"表示Resources文件夹中的Prefabs文件夹中的名叫Cube的资源。</param>/// <param name="callback">资源加载完毕后要执行的逻辑</param>public void LoadAsync<T>(string path, UnityAction<T> callback = null) where T : Object{MonoManager.Instance.StartCoroutine(LoadAsyncCoroutine(path, callback));}IEnumerator LoadAsyncCoroutine<T>(string path, UnityAction<T> callback = null) where T : Object{ResourceRequest resourceRequest = Resources.LoadAsync<T>(path);yield return resourceRequest;callback?.Invoke(resourceRequest.asset as T);}#endregion#region 卸载资源/// <summary>/// <para>异步卸载所有用Resources方式加载到内存中且当前没有被任何地方使用的资源。</para>/// <para>例如要卸载某一个用Resources方式加载的预制体,则必须确保场景中所有这个预制体创建的物体都被销毁了,且这个预制体资源没有赋值给任何脚本中的任何变量。</para>/// <para>如果有,可以把该变量也赋值为null,这样本方法才能成功释放它。</para>/// </summary>/// <param name="callback">资源卸载完毕后执行的逻辑</param>public void UnloadUnusedAssets(UnityAction callback = null){MonoManager.Instance.StartCoroutine(UnLoadUnusedAssetsCoroutine(callback));}IEnumerator UnLoadUnusedAssetsCoroutine(UnityAction callback = null){//异步操作对象,记录了异步操作的数据。AsyncOperation asyncOperation = Resources.UnloadUnusedAssets();//等待资源卸载while (asyncOperation.progress < 1)yield return CoroutineTool.WaitForFrame();//资源卸载完毕后执行的逻辑callback?.Invoke();}/// <summary>/// <para>同步卸载指定的资源。</para>/// <para>只能卸载非GameObject类型和Component类型,例如Mesh、Texture、Material、Shader。如果卸载了不让卸载的资源,则会报错。</para>/// <para>如果随后加载的任何场景或资源引用了该资源,将导致从磁盘中加载该资源的新实例。此新实例将与先前卸载的对象相互独立。</para>/// </summary>/// <param name="assetToUnload">要卸载的资源</param>public void UnloadAsset(Object assetToUnload){Resources.UnloadAsset(assetToUnload);}#endregion
}

完结

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!

好了,我是向宇,https://xiangyu.blog.csdn.net

一位在小公司默默奋斗的开发者,闲暇之余,边学习边记录分享,站在巨人的肩膀上,通过学习前辈们的经验总是会给我很多帮助和启发!如果你遇到任何问题,也欢迎你评论私信或者加群找我, 虽然有些问题我也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~
在这里插入图片描述

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

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

相关文章

C++ 语言特性07 - 静态成员的初始化

一&#xff1a;概述 1. 静态成员变量通常在类定义内部声明&#xff0c;并在类定义外部定义和初始化。 class MyClass { public:static int staticVar; // 声明 };int MyClass::staticVar 42; // 定义和初始化 2. 从C11开始&#xff0c;可以在类内直接初始化静态数据成员&am…

无源码实现免登录功能

因项目要求需要对一个没有源代码的老旧系统实现免登录功能&#xff0c;系统采用前后端分离的方式部署&#xff0c;登录时前端调用后台的认证接口&#xff0c;认证接口返回token信息&#xff0c;然后将token以json的方式存储到cookie中&#xff0c;格式如下&#xff1a; 这里有…

H.264编解码工具 - x264

一、简介 x264是一个开源的H.264/AVC视频编码库,它可以将视频数据压缩成H.264格式,并且可以从H.264格式解码出原始视频数据。 x264是以C语言编写的,并且可以在多个平台上使用,包括Windows、Linux和Mac OS等操作系统。 x264具有很高的编码效率和视频质量,它支持多种编码…

HTTPS加密流程

本文尽量用最小的篇幅来介绍HTTPS的加密过程&#xff0c;如果还看不懂可以参考文末尾的文章。 加密算法 先简单介绍一下HTTPS中使用的是混合加密算法&#xff0c;即对称加密和非对称加密的混合使用&#xff1a; 1.对称加密:顾名思义就是加密和解密都是使用同一个密钥。 优点…

MySQL 问题小结

mysqld --initialize 初始化 data 文件夹 初始化的密码在这个 err 文件夹中

DC00025【含论文】基于协同过滤推荐算法springboot视频推荐管理系统

1、项目功能演示 DC00025【含文档】基于springboot短视频推荐管理系统协同过滤算法视频推荐系统javaweb开发程序设计vue 2、项目功能描述 短视频推荐系统分为用户和系统管理员两个角色 2.1 用户角色 1、用户登录、用户注册 2、视频中心&#xff1a;信息查看、视频收藏、点赞、…

Pyenv管理Python版本,conda之外的另一套python版本管理解决方案

简介 Pyenv 是一个 python 解释器管理工具&#xff0c;可以对计算机中的多个 python 版本进行管理和切换。为什么要用 pyenv 管理python呢&#xff0c;用过的 python 人都知道&#xff0c;python 虽然是易用而强大的编程语言&#xff0c;但是 python 解释器却有多个版本&#…

数据链路层 ——MAC

目录 MAC帧协议 mac地址 以太网帧格式 ARP协议 ARP报文格式​编辑 RARP 其他的网络服务或者协议 DNS ICMP协议 ping traceroute NAT技术 代理服务器 网络层负责规划转发路线&#xff0c;而链路层负责在网络节点之间的转发&#xff0c;也就是"一跳"的具体传输…

Qt_绘图

目录 1、绘图核心类 2、QPainter类的使用 2.1 绘制线段 2.2 绘制矩形 2.3 绘制圆形 2.4 绘制文本 3、QPen类的使用 3.1 使用画笔 4、QBrush类的使用 4.1 使用画刷 5、绘制图片 5.1 测试QPixmap 5.1.1 图片移动 5.1.2 图标缩小 5.1.3 旋转图片 5.1.4 将…

esp32 命令行 编译 下载 调试

选择芯片型号 idf.py set-target esp32s3 编译程序 idf.py build 下载程序 idf.py -p PORT [-b BAUD] flash 串口监听 idf.py -p PORT monitor 退出监听 Ctrl] 使用VScode打开文件夹 code . 快速入门 - ESP32 - — ESP-IDF 编程指南 v4.4.3 文档 https://docs.espressif.com/pr…

【四】Spring Cloud OpenFeign原理分析

Spring Cloud OpenFeign原理分析 概述 Spring Cloud 微服务实践也有挺多年了&#xff0c;一直想着总结一下这系列的知识点&#xff0c;最近终于下定决心来出一个Spring Cloud 系列文章了。本文主要围绕fegin组件来进行讲解&#xff0c;文中将会给出基础使用的示例&#xff0c;还…

java将mysql表结构写入到word表格中

文章目录 需要的依赖 需要的依赖 <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.9</version> </dependency> <!--07版本的&#xff0c;行数不受限制--> <dependency>&l…

Python中的属性装饰器:解锁数据封装的新境界

引言 随着软件复杂度的不断增加&#xff0c;如何有效地管理类内部的数据变得愈发重要。属性装饰器作为一种强大的工具&#xff0c;不仅简化了代码&#xff0c;还增强了程序的可读性和可维护性。通过使用属性装饰器&#xff0c;我们可以轻松地实现对类属性的读取、修改以及删除…

docker-compose 快速部署clickhouse集群

在本教程中&#xff0c;我们将学习如何使用 Docker Compose 部署一个带有三节点的 ClickHouse 集群&#xff0c;并使用 ZooKeeper 作为分布式协调服务。 前提条件 注意事项&#xff1a; 镜像版本号注意保持一致 [zookeeper:3.7, clickhouse/clickhouse-server:22.5.4]config…

gcc选项-fno-access-control 使用

背景&#xff1a; 在进行eigen库进行移植时&#xff0c;总是报编译错误&#xff1a; error: struct std::basic_stringbuf<_CharT, _Traits, _Alloc>::__xfer_bufptrs redeclared with different access struct __xfer_bufptrs &#xff0c;单独写一个测试程序使用eig…

uniapp微信小程序使用ucharts遮挡自定义tabbar的最佳解决方案

如图所示&#xff1a; 使用的ucharts遮挡住了我自定义的tabbar&#xff08;如果不是提需求的有病&#xff0c;我才不会去自定义tabbar&#xff09; 查阅了不少文档&#xff0c;说是开启 ucharts 的 canvas2d 即可&#xff1a; 官网文档地址&#xff1a; uCharts官网 - 秋云…

Android Debug Bridge(ADB)完全指南

文章目录 前言一、什么是ADB&#xff1f;二、ADB的工作原理ADB由三个部分组成&#xff1a; 三、如何安装ADBWindows系统&#xff1a;macOS和Linux系统&#xff1a; 四、ADB常用指令大全设备相关操作1. 查看连接的设备&#xff1a;2. 重启设备&#xff1a;3. 进入Bootloader模式…

资源《Arduino 扩展板1-LED灯》说明。

资源链接&#xff1a;Arduino 扩展板1-LED灯 1.文件明细&#xff1a; 2.文件内容说明 包含&#xff1a;AD工程、原理图、PCB。 3.内容展示 4.简述 该文件为PCB工程&#xff0c;采用AD做的。 该文件打板后配合Arduino使用&#xff0c;属于Arduino的扩展板。 该文件主要有…

docker 私有仓库的镜像删除

目录 获取token1. base64 用户名 密码2. 先请求要请求的接口3. 请求接口 auth4. 拿着 token, 去请求接口 请求 tag 列表接口1. 去请求token2. 拿着token去请求 镜像 tag 列表 删除镜像1. 先获取镜像 tag 的 sha2562. 删除镜像 错误: {"errors":[{"code":&q…

Web3.0 应用项目

Web3.0 是下一代互联网的概念&#xff0c;旨在去中心化、用户拥有数据控制权和通过区块链技术实现信任的网络。Web3.0的应用项目主要集中在区块链、加密货币、去中心化应用 (DApps)、去中心化金融 (DeFi)、NFT&#xff08;非同质化代币&#xff09;等领域。以下是一些典型的 We…