Unity功能模块一对话系统(4)实现个性文本标签
本期我们将了解如何在TMPro中自定义我们的标签样式,并实现两种有趣的效果。
一.需求描述
1.定义<float>格式的标签,实现标签处延迟打印功能
2.定义<r=" "></r>格式的标签,实现标签区间内文本片段的注释显示功能
3.补充文本多种打印样式功能。
二.自定义标签样式
首先我们需要借助预处理器来读取到我们的目标格式的标签,并记录标签内的相关信息
基本思路:通过ITextPreprocessor接口实现预处理器的预加工函数PreprocessText(),读取到文本中的自定义标签格式并记录标签内信息。
1.实现接口方法
public class AdvancedTextPreprocessor : ITextPreprocessor{public string PreprocessText(string text){}}
2.提取标签
(1)使用正则表达式来匹配<>的类html格式。
public string PreprocessText(string text){string processingText = text;string pattern = "<.*?>";//定义一个正则表达式 "<.*>" 用于匹配所有以 < 开头、> 结尾的字符串。贪婪模式,即它会匹配最远的 >Match match = Regex.Match(processingText, pattern);//首次匹配,查找所有富文本标签while (match.Success) //尝试匹配富文本标签{match = Regex.Match(processingText, pattern);//继续匹配,查找下一个标签}processingText = text;return processingText;
}//正则表达式概念// . 代表任意字符//*代表前一个字符出现0次或多次//+代表前一个字符出现1次或多次//?代表前一个字符出现0次或1次
这里我们定义了<.*?>这种文本模式,下方代码将在用户文本中查找符合模式的文本片段match。
Match match = Regex.Match(processingText, pattern);//按照pattern模式来匹配用户文本中符合格式的文本(含<>)
3.记录标签内信息
下面我们需要记录下我们的自定义标签内的信息。
1.定义存储结构
/// <summary>
/// 打印延迟字典【读取标签<float>,遇到将延迟float秒后打印后面内容】
/// </summary>
public Dictionary<int, float> IntervalDictionary = new Dictionary<int, float>();//自定义打印标签字典/// <summary>
/// 注释标签列表
/// </summary>
public List<RubyData> rubyList = new List<RubyData>();
这里我使用字典存储延迟标签信息,将延迟标签的位置偏移作为键,延迟长度作为值。
使用列表来存储注释数据结构。成员是Rubydata类的实例。
Rubydata类中定义了3种属性:注释自身在文本中的起止位置偏移startIndex和终止位置偏移endIndex,以及注释内容contnet。
RubyData类如下
/// <summary>/// 注释数据/// </summary>public class RubyData{public RubyData(int _startIndex, string _content){startIndex = _startIndex;rubyContent = _content;}public int startIndex { get; }public string rubyContent { get; }public int endIndex { get; set; }}
2.匹配<>标签内的文本信息
下方代码功能是去除match文本中包含的<>字符,得到标签内的信息label。
string label = match.Value.Substring(1, match.Length - 2);
3.标签内信息的存储逻辑
(1)读取<float>格式标签内容
//自定义延迟打印标签【规定<float>】并记录在打印间隔标签字典中if (float.TryParse(label, out float result))IntervalDictionary[match.Index - 1] = result;
此处由于标签内部就是一个float类型的数据,所以我们可以直接就爱那个标签记录在我们的打印间隔标签字典中
(2)读取<r=" "></r>格式标签内容
//自定义注释标签【规定<r="">】录入注释列表//注释标签开启if (Regex.IsMatch(label, "^r=.+")) //^:表示字符串的开头。这个符号确保匹配的字符串必须从开头开始rubyList.Add(new RubyData(match.Index, label.Substring(2)));//注释标签终止else if (Regex.IsMatch(label, "/r")){if (rubyList.Count > 0)rubyList[rubyList.Count - 1].endIndex = match.Index - 1;}
4.去除标签文本
由于我们在用户文本中含有<>的类html标签,但是最终是不需要显示的,所以我们还需要在用户文本的基础上去除我们的标签(替换为空字符串),才能得到最终的渲染文本。
pattern = @"(<(\d+)(\.\d+)?>)|(</r>)|(<r=.*?>)";//使用 @ 前缀可以避免在字符串中使用转义字符//将处理文本中符合pattern规则的字符串 替换为空字符串""processingText = Regex.Replace(processingText, pattern, "");
完整源码见后文。
三.实现自定义文本效果
1.延迟打印功能
现在我们已经可以存储文本中的自定义标签内的信息,我们现在来实现一下文本的自定义效果。
我们前面已经实现了打字机的效果,实际上的延时打印功能,就是在打字函数的携程循环中等待的迭代函数。
if (selfPreprocessor.IntervalDictionary.TryGetValue(typingIndex, out float result))yield return new WaitForSecondsRealtime(result);elseyield return new WaitForSecondsRealtime(defalutInterval);
上句代码用来判断文本中当前打印位置处会否是延迟标签所在位置。如果恰好是字典中延迟标签的位置,则返回字典中的的当前位置键对应的float值作为输入执行携程延迟函数。否则按照默认间隔执行打印延迟。
2.注释功能
我们具体会用到两个方法。
(1)生成并设置注释
void SetRubyText(RubyData data)
{GameObject ruby = Instantiate(Resources.Load<GameObject>("RubyText"), transform);ruby.GetComponent<TextMeshProUGUI>().SetText(data.rubyContent);ruby.GetComponent<TextMeshProUGUI>().color = textInfo.characterInfo[data.startIndex].color;ruby.transform.localPosition = (textInfo.characterInfo[data.startIndex].topLeft + textInfo.characterInfo[data.endIndex].topRight) / 2 - new Vector3(0, 10, 0);
}
这里我们传入一个Rubydata实例,设置预制件文本,颜色及位置。
(2)判断当前位置是否是注释的起始位
/// <summary>/// 读取一个位置是否就是Ruby起始位/// </summary>/// <param name="index"></param>/// <param name="data"></param>/// <returns></returns>public bool TryGetRubyText(int index, out RubyData data){data = new RubyData(0, "");foreach (RubyData item in rubyList){if (item.startIndex == index){data = item;return true;}}return false;}
}
每打印到一个位置,我们都需要判断当前位置是否是注释标签的起始位。如果是,将调用生成注释预制件的函数。
四.改进文本显示逻辑
现在我们去AdvancedText类中改进一下前面实现的文本显示逻辑。
增添字段
Coroutine typingCor;//存储打字携程,易于中断Action OnFinish; //文本打印结束的回调委托
这里的携程字段使用来记录我们的打字机携程的,实际情况中我们会遇到 打断正在打印中文本 的需求。存储到一个携程变量中将易于管理。
增添枚举
我们使用一个枚举来决定文本以什么形式显示。(见下方)
public enum E_DisplayType
{Defalut,Fading,Typing
}
Defalut模式:文本采用 整体直接显示。
Fading模式:文本采用 整体淡入显示。
Typing模式:文本采用 打字机淡入效果显示。
我们现在实现一下各种打印样式的函数。
Defalut模式显示方法
/// <summary>/// 文本整体直接显示/// </summary>void DefalutDisplay(Action action = null){for (int i = 0; i < m_characterCount; i++)SetSingleCharacterAlpha(i, 255);action?.Invoke();}
Fading模式显示方法
/// <summary>/// 文本整体淡入显示/// </summary>void FadingDisplay(float fadeDuration,Action action=null){for (int i = 0; i < m_characterCount; i++)StartCoroutine(FadeInCharacter(i, fadeDuration));action?.Invoke();}
Typing模式显示方法
/// <summary>/// 文本打字机显示/// </summary>/// <returns></returns>IEnumerator TypingDisplay(float fadeDuration,Action action = null){ForceMeshUpdate();for (int i = 0; i < m_characterCount; i++){SetSingleCharacterAlpha(i, 0);}typingIndex = 0;while (typingIndex < m_characterCount){//SetSingleCharacterAlpha(typingIndex,255); //无淡入打字机效果StartCoroutine(FadeInCharacter(typingIndex, fadeDuration)); //淡入打字机效果if (selfPreprocessor.IntervalDictionary.TryGetValue(typingIndex, out float result))yield return new WaitForSecondsRealtime(result);elseyield return new WaitForSecondsRealtime(defalutInterval);typingIndex++;}action?.Invoke();}
文本显示方法
我们还需要一个函数作为暴露给外部的应用接口,客户端可以选择不同的文本显示样式。
public IEnumerator ShowText(string content, E_DisplayType displayType, float duration){if (typingCor != null){StopCoroutine(typingCor);}typingCor = null;SetText(content);yield return null;TextDisAppear();switch (displayType){case E_DisplayType.Defalut:DefalutDisplay();SetAllRubyTexts();break;case E_DisplayType.Fading:FadingDisplay(duration);SetAllRubyTexts();break;case E_DisplayType.Typing:typingCor = StartCoroutine(TypingDisplay(duration));break;default:break;}}
五.功能测试
在测试脚本中我们调用AdvancedText实例的携程来显示文本。
StartCoroutine(advancedText.ShowText(content,displayType,duration));
编辑器内选择打印样式。
运行效果
这里我是做了一个按键输入功能,通过按键显示并开始打印文本,但调用文本打印的逻辑是一致的。如果大家对UI动效有有兴趣的话我后面可以出一期关于UI的代码框架及动效功能的解决方案。
六.完整源码
AdvancedTextPreprocessor类
using System.Collections.Generic;
using System.Text.RegularExpressions;
using TMPro;namespace DialogueDemo
{public class AdvancedTextPreprocessor : ITextPreprocessor{/// <summary>/// 打印延迟字典【读取标签<float>,遇到将延迟float秒后打印后面内容】/// </summary>public Dictionary<int, float> IntervalDictionary = new Dictionary<int, float>();//自定义打印标签字典public List<RubyData> rubyList = new List<RubyData>();public string PreprocessText(string text){IntervalDictionary.Clear();string processingText = text;string pattern = "<.*?>";//定义一个正则表达式 "<.*>" 用于匹配所有以 < 开头、> 结尾的字符串。贪婪模式,即它会匹配最远的 >Match match = Regex.Match(processingText, pattern);//首次匹配,查找所有富文本标签while (match.Success) //尝试匹配富文本标签{string label = match.Value.Substring(1, match.Length - 2);//自定义延迟打印标签【规定<float>】并记录在打印间隔标签字典中if (float.TryParse(label, out float result))IntervalDictionary[match.Index - 1] = result;//自定义注释标签【规定<r="">】录入注释列表//注释标签开启else if (Regex.IsMatch(label, "^r=.+")) //^:表示字符串的开头。这个符号确保匹配的字符串必须从开头开始rubyList.Add(new RubyData(match.Index, label.Substring(2)));//注释标签终止else if (Regex.IsMatch(label, "/r")){if (rubyList.Count > 0)rubyList[rubyList.Count - 1].endIndex = match.Index - 1;}processingText = processingText.Remove(match.Index, match.Length);//读取此打印间隔标签后,删除此标签if (Regex.IsMatch(label, "^sprite.+")) //如果标签格式是精灵,需要一个占位符processingText.Insert(match.Index, "*");match = Regex.Match(processingText, pattern);//继续匹配,查找下一个标签}processingText = text;//正则表达式概念// . 代表任意字符//*代表前一个字符出现0次或多次//+代表前一个字符出现1次或多次//?代表前一个字符出现0次或1次pattern = @"(<(\d+)(\.\d+)?>)|(</r>)|(<r=.*?>)";//使用 @ 前缀可以避免在字符串中使用转义字符//简单解释:本句代码实现了读取<>中的整数或小数的功能/* (\d +):\d + 是一个数字匹配模式,它匹配一个或多个数字字符。+表示前面的模式(数字)可以匹配一个或多个字符。() 是捕获组的标记,这样 \d + 匹配到的数字部分就会被捕获到组中,可以在后续处理中使用。(\.\d +)?:\. 匹配一个字面上的点(.)。点号是一个元字符,在正则中表示任意字符,但在这里需要加 \ 进行转义,表示字面上的点号。\d + 匹配一个或多个数字,表示小数点后面的部分。() ? 表示这个捕获组是可选的,即小数部分不是必需的。如果没有小数部分,这一部分会被忽略。*///将处理文本中符合pattern规则的字符串 替换为 后面的字符串processingText = Regex.Replace(processingText, pattern, "");return processingText;}/// <summary>/// 读取一个位置是否就是Ruby起始位/// </summary>/// <param name="index"></param>/// <param name="data"></param>/// <returns></returns>public bool TryGetRubyText(int index, out RubyData data){data = new RubyData(0, "");foreach (RubyData item in rubyList){if (item.startIndex == index){data = item;return true;}}return false;}}/// <summary>/// 注释数据/// </summary>public class RubyData{public RubyData(int _startIndex, string _content){startIndex = _startIndex;rubyContent = _content;}public int startIndex { get; }public string rubyContent { get; }public int endIndex { get; set; }}
}
AdvancedText类
using System;
using System.Collections;
using TMPro;
using UnityEngine;namespace DialogueDemo
{public class AdvancedText : TextMeshProUGUI{int typingIndex;float defalutInterval = 0.08f;Coroutine typingCor;//存储打字携程,易于中断Action OnFinish;AdvancedTextPreprocessor selfPreprocessor => (AdvancedTextPreprocessor)textPreprocessor;private void Init(){SetText("");ClearRubyText();}public AdvancedText(){textPreprocessor = new AdvancedTextPreprocessor();}public void TextDisAppear(){for (int i = 0; i < m_characterCount; i++)SetSingleCharacterAlpha(i, 0);}public IEnumerator ShowText(string content, E_DisplayType displayType, float duration){if (typingCor != null){StopCoroutine(typingCor);}typingCor = null;SetText(content);yield return null;TextDisAppear();switch (displayType){case E_DisplayType.Defalut:DefalutDisplay();SetAllRubyTexts();break;case E_DisplayType.Fading:FadingDisplay(duration);SetAllRubyTexts();break;case E_DisplayType.Typing:typingCor = StartCoroutine(TypingDisplay(duration));break;default:break;}}/// <summary>/// 直接显示/// </summary>void DefalutDisplay(Action action = null){for (int i = 0; i < m_characterCount; i++)SetSingleCharacterAlpha(i, 255);action?.Invoke();}/// <summary>/// 整体淡入/// </summary>void FadingDisplay(float fadeDuration,Action action=null){for (int i = 0; i < m_characterCount; i++)StartCoroutine(FadeInCharacter(i, fadeDuration));action?.Invoke();}/// <summary>/// 打字机显示/// </summary>/// <returns></returns>IEnumerator TypingDisplay(float fadeDuration,Action action = null){ForceMeshUpdate();for (int i = 0; i < m_characterCount; i++){SetSingleCharacterAlpha(i, 0);}typingIndex = 0;while (typingIndex < m_characterCount){//SetSingleCharacterAlpha(typingIndex,255); //无淡入打字机效果StartCoroutine(FadeInCharacter(typingIndex, fadeDuration)); //淡入打字机效果if (selfPreprocessor.IntervalDictionary.TryGetValue(typingIndex, out float result))yield return new WaitForSecondsRealtime(result);elseyield return new WaitForSecondsRealtime(defalutInterval);typingIndex++;}action?.Invoke();}/// <summary>/// 设置单字符的透明度(每个字符都是由网格(含4个顶点)渲染)/// </summary>/// <param name="index"></param>/// <param name="newAlpha">newalpha范围为0~255</param>void SetSingleCharacterAlpha(int index, byte newAlpha){TMP_CharacterInfo character = textInfo.characterInfo[index];//获取文本内容索引下的单个字符if (!character.isVisible)return;int matIndex = character.materialReferenceIndex;//获取字符材质索引int vertexIndex = character.vertexIndex;//获取字符顶点索引for (int i = 0; i < 4; i++){textInfo.meshInfo[matIndex].colors32[vertexIndex + i].a = newAlpha;}UpdateVertexData();//更新顶点数据}/// <summary>/// 单字符淡入/// </summary>/// <param name="index"></param>/// <param name="duration"></param>/// <returns></returns>IEnumerator FadeInCharacter(int index, float duration){//如果找到Ruby起始位,设置Ruby预制件Debug.Log(selfPreprocessor.TryGetRubyText(index, out var data1));if (selfPreprocessor.TryGetRubyText(index, out RubyData data))SetRubyText(data);if (duration <= 0)SetSingleCharacterAlpha(index, 255);else{float timer = 0;while (timer < duration){timer = Mathf.Min(duration, timer + Time.unscaledDeltaTime);SetSingleCharacterAlpha(index, (byte)(255 * (timer / duration)));yield return null;}}}void SetRubyText(RubyData data){GameObject ruby = Instantiate(Resources.Load<GameObject>("RubyText"), transform);ruby.GetComponent<TextMeshProUGUI>().SetText(data.rubyContent);ruby.GetComponent<TextMeshProUGUI>().color = textInfo.characterInfo[data.startIndex].color;ruby.transform.localPosition = (textInfo.characterInfo[data.startIndex].topLeft + textInfo.characterInfo[data.endIndex].topRight) / 2 - new Vector3(0, 10, 0);}/// <summary>/// 清除当前的所有注释/// </summary>void ClearRubyText(){foreach (var item in GetComponentsInChildren<TextMeshProUGUI>()){if (item != this)Destroy(item.gameObject);}}/// <summary>/// 用于跳过对话直接显示所有注释/// </summary>void SetAllRubyTexts(){foreach (var item in selfPreprocessor.rubyList){SetRubyText(item);}}}
}
七.尾声
在 Unity 的 TextMeshPro中,文本标签(如 <color=red>...</color>)的处理方式不同于我们在自定义 AdvancedTextPreprocessor 类中的实现。TextMeshPro 之所以能正确处理 <color=red> </color> 等标签,原因在于它内部已经预先实现了一个功能强大的解析器,用于识别和处理各种富文本标签。TMP处理这些标签的方法是通过其 TextParser 类内部的规则和机制。具体的实现位于 TextMeshPro 的源码中,这些规则和方法是在 TextMeshPro 的组件中预定义的。当你将含有富文本标签的字符串传递给 TMP_Text 组件时,TextMeshPro 会自动解析这些标签并应用对应的样式。这与 AdvancedTextPreprocessor 类不同,后者是我们自己实现的自定义处理器,它仅仅处理我们通过正则表达式解析并手动处理的标签(例如延迟打印标签、注释标签等),并不会干预 TextMeshPro 内部已经定义的标准标签处理。
本篇完
相关文章:

Unity功能模块一对话系统(4)实现个性文本标签
本期我们将了解如何在TMPro中自定义我们的标签样式,并实现两种有趣的效果。 一.需求描述 1.定义<float>格式的标签,实现标签处延迟打印功能 2.定义<r" "></r>格式的标签,实现标签区间内文本片段的注释显示功能…...

git在idea中操作频繁出现让输入token或用户密码,可以使用凭证助手(使用git命令时输入的用户密码即可) use credential helper
1、打开 idea 设置,找到 git 路径 File | Settings | Version Control | Git 2、勾选 Use credential helper 即可...
毫米波雷达技术:(九)快时间窗和慢时间窗的概念
(一)快时间窗: 快时间窗通常指的是在雷达脉冲周期内,对每个脉冲回波进行采样的时间段。这个时间段非常短,通常在 0 − 100 n s 0-100ns 0−100ns 。在快时间窗内,雷达系统会对接收到的回波信号进行高分辨…...

宠物行业的出路:在爱与陪伴中寻找增长新机遇
在当下的消费市场中,如果说有什么领域能够逆势而上,宠物行业无疑是一个亮点。当人们越来越注重生活品质和精神寄托时,宠物成为了许多人的重要伴侣。它们不仅仅是家庭的一员,更是情感的寄托和生活的调剂。然而,随着行业…...
Android MQTT关于断开连接disconnect报错原因
最近项目遇到一个需求,就是在登录状态的时候。才能接收到消息。所有我在上线,下线状态的时候。做了MQTT断开和连接的动作。然后就是发生了。我们标题的这关键点了。直接报错了。报错的内容如下: MqttAndroidClient unregisterRecevicer afte…...
Unity3D中Huatuo可行性的思维实验详解
引言 Unity3D作为一款功能强大的跨平台游戏引擎,在游戏开发领域具有举足轻重的地位。它不仅支持2D和3D游戏开发,还广泛应用于虚拟现实、建筑可视化等领域。其中,Huatuo作为一个强大的热更新解决方案,通过扩展Unity的IL2CPP运行时…...
ES-聚合分析
ES的聚合分析 什么是ES的聚合分析 ElasticSearch除搜索意外,提供的针对ES数据进行统计分析的功能通过聚合,我们会得到一个数据的概览,是分析和总结全套的数据,而不是寻找单独的文档高性能,只要一条语句就可以得到分析…...

【CSS in Depth 2 精译_093】16.2:CSS 变换在动效中的应用(上)—— 图标的放大和过渡效果的设置
当前内容所在位置(可进入专栏查看其他译好的章节内容) 第五部分 添加动效 ✔️【第 16 章 变换】 ✔️ 16.1 旋转、平移、缩放与倾斜 16.1.1 变换原点的更改16.1.2 多重变换的设置16.1.3 单个变换属性的设置 16.2 变换在动效中的应用 ✔️ 16.2.1 放大图…...

Linux Debian安装ClamAV和命令行扫描病毒方法,以及用Linux Shell编写了一个批量扫描病毒的脚本
ClamAV是一个开源的跨平台病毒扫描引擎,用于检测恶意软件、病毒、木马等安全威胁。 一、Linux Debian安装ClamAV 在Linux Debian系统上安装ClamAV,你可以按照以下步骤进行: 更新软件包列表: 打开终端并更新你的软件包列表&#…...
Spring创建异步线程,使用@Async注解时不指定value可以吗?
在Spring中使用Async注解时,不指定value是可以的。如果没有指定value(即线程池的名称),Spring会默认使用名称为taskExecutor的线程池。如果没有定义taskExecutor线程池,则Spring会自动创建一个默认的线程池。 默认行为…...

二分和离散化
为什么把二分和离散化放一起:因为离散化其实是一种二分整数的过程。 二分 相信大家都接触过二分查找(折半查找),这就是二分的思想。 二分通过每次舍弃一半并不存在答案的区间,进而快速锁定要求的答案(二…...

深度学习实战102-基于深度学习的网络入侵检测系统,利用各种AI模型和pytorch框架实现网络入侵检测
大家好,我是微学AI,今天给大家介绍一下深度学习实战102-基于深度学习的网络入侵检测系统,利用各种AI模型和pytorch框架实现网络入侵检测。近年来,网络安全威胁日益严峻,传统基于规则的方法难以应对复杂多变的入侵手段。 深度学习技术凭借其强大的特征学习能力和自适应性,…...

vue3使用element-plus,解决 el-table 多选框,选中后翻页再回来选中失效问题
问题:勾选的数据分页再回来回消失 1.在el-table中加 :row-key"getRowKey" const getRowKey (row) > { return row.id; // id必须是唯一的 }; 2.给type为selection的el-table-column添加上reserve-selection属性 <el-tableref"multipleTab…...

网络的类型
BMA---广播型多路访问--在一个网段内可以放置多个物理节点,同时该范围内可以实施广播洪泛机制 【1】以太网-->共享型 属性典型的 BMA类型;以太网技术的核心为频分一在同一物理介质上,使用多个相互不干涉的频率电波来共同传输数据,实现带宽的不断提升…...

实现类似gpt 打字效果
1. css的动画(animation) css中实现动画有两种方式:transition过渡动画、 animation自定义动画。 具体的可以看MDN链接:https://developer.mozilla.org/zh-CN/docs/Web/CSS/animation 使用keyframes自定义关键帧动画并未其命名使用自定义动…...
项目需求分析流程
项目需求分析是软件开发或任何工程项目中至关重要的第一步。它帮助确保团队理解客户的需求,并为后续的设计、开发和测试工作提供指导。以下是一个详细的需求分析流程: 一、确定项目目标 与利益相关者沟通:包括但不限于客户、最终用户、销售…...

idea连接SQL Server数据库_idea连接sqlserver数据库
4.设置密码(这一步可以在安装数据库时就可以完成),如果觉得用户名有问题,也可以修改用户名 5.查看SQL Server端口号(默认端口:1433),选择SQL Server2019配置管理器 6.打开SQL Server…...

Scala_【2】变量和数据类型
第二章 注释标识符的命名规范命名规则关键字 变量字符串输出数据类型关系变量和数据类型整数类型(Byte、Short、Int、Long)浮点类型(Float、Double)字符类型(Char)布尔类型(Boolean)…...

u3d中JSON数据处理
一.认识JSON 1.1 Json概述 JSON(JavaScript Object Notation,JavaScript对象表示法)JSON和XML是比较类似的技术,都是用来存储文本信息数据的;相对而言,JSON比XML体积更小巧,但是易读性不如XML…...

idea 安装插件(在线安装、离线安装)
目录 在线安装 离线安装 在线安装 1、打开IntelliJ IDEA 2024.x软件, 点击file-Settings 2、点击搜索框,输入plugins,找到plugins列,输入xxx软件--点击install 安装 3、重启idea 离线安装 1、在官网上下载插件包 (1&…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...

LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...

Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...