当前位置: 首页 > news >正文

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中自定义我们的标签样式&#xff0c;并实现两种有趣的效果。 一.需求描述 1.定义<float>格式的标签&#xff0c;实现标签处延迟打印功能 2.定义<r" "></r>格式的标签&#xff0c;实现标签区间内文本片段的注释显示功能…...

Vue.js前端框架教程15:Vue父子组件之间的通信ref、emits

文章目录 1. 属性传递(Props)2. 事件监听( Emits)3. `ref` 引用4. `provide` 和 `inject`5. 插槽(Slots)在 Vue 3 中,父子组件之间的通信可以通过多种方式实现,包括属性传递、事件监听、插槽以及 ref 和 provide/inject。以下是这些通信方式的详解: 1. 属性传递(Pro…...

Python 实现 冒泡排序算法示例

冒泡排序算法示例 冒泡排序&#xff08;Bubble Sort&#xff09;是一种简单的排序算法。它重复地遍历要排序的列表&#xff0c;比较相邻的元素&#xff0c;并交换它们的位置&#xff0c;如果它们的顺序错误。这个过程会重复进行&#xff0c;直到没有需要交换的元素为止&#x…...

《机器学习》--线性回归模型详解

线性回归模型是机器学习中的一种重要算法&#xff0c;以下是对其的详细解释&#xff1a; 一、定义与原理 线性回归&#xff08;Linear Regression&#xff09;是利用数理统计中回归分析&#xff0c;来确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法。线性回归…...

Django项目部署到服务器

文章目录 django项目部署到服务器在服务器上安装Django和依赖&#xff1a;项目代码上传配置数据库收集静态文件配置Web服务器配置Gunicorn&#xff08;WSGI服务器&#xff09;启动/停止/重载systemd服务。 django项目部署到服务器 在服务器上安装Django和依赖&#xff1a; su…...

CSDN编辑器

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…...

如何免费解锁 IPhone 网络

您是否担心 iPhone 上的网络锁定&#xff1f;如果您的 iPhone 被锁定到特定运营商&#xff0c;解锁它可以连接到不同的运营商。好吧&#xff0c;我们为您准备了一份指南。 iPhone运营商免费解锁将是小菜一碟。在我们的解锁运营商 iphone 免费指南中。我们为您提供了一份简介&am…...

Trimble天宝X9三维扫描仪为建筑外墙检测提供了全新的解决方案【沪敖3D】

随着城市化进程的快速推进&#xff0c;城市高层建筑不断增多&#xff0c;对建筑质量的要求也在不断提高。建筑外墙检测&#xff0c;如平整度和垂直度检测&#xff0c;是衡量建筑质量的重要指标之一。传统人工检测方法不仅操作繁琐、效率低下&#xff0c;还难以全面反映墙体的真…...

微服务のGeteWay

目录 概念&#xff1a; 三大核心&#xff1a; 工作流程&#xff1a; 9527网关如何做路由映射&#xff1a; GetWay高级特性&#xff1a; 按服务名动态路由服务&#xff1a; 断言Route Predicate Factories &#xff1a; 获取当前时区时间&#xff1a; After Route &…...

Golang 中 Goroutine 的调度

Golang 中 Goroutine 的调度 Golang 中的 Goroutine 是一种轻量级的线程&#xff0c;由 Go 运行时&#xff08;runtime&#xff09;自动管理。Goroutine 的调度基于 M:N 模型&#xff0c;即多个 Goroutine 可以映射到多个操作系统线程上执行。以下是详细的调度过程和策略&…...

MyBatis使用的设计模式

目录 1. 工厂模式&#xff08;Factory Pattern&#xff09; 2. 单例模式&#xff08;Singleton Pattern&#xff09; 3. 代理模式&#xff08;Proxy Pattern&#xff09; 4. 装饰器模式&#xff08;Decorator Pattern&#xff09; 5. 观察者模式&#xff08;Observer Patt…...

淺談Cocos2djs逆向

前言 簡單聊一下cocos2djs手遊的逆向&#xff0c;有任何相關想法歡迎和我討論^^ 一些概念 列出一些個人認為比較有用的概念&#xff1a; Cocos遊戲的兩大開發工具分別是CocosCreator和CocosStudio&#xff0c;區別是前者是cocos2djs專用的開發工具&#xff0c;後者則是coco…...

选择器(结构伪类选择器,伪元素选择器),PxCook软件,盒子模型

结构为类选择器 伪元素选择器 PxCook 盒子模型 (内外边距&#xff0c;边框&#xff09; 内外边距合并&#xff0c;塌陷问题 元素溢出 圆角 阴影: 模糊半径&#xff1a;越大越模糊&#xff0c;也就是越柔和 案例一&#xff1a;产品卡片 <!DOCTYPE html> <html lang&q…...

CentOS 7系统 OpenSSH和OpenSSL版本升级指南

文章目录 CentOS 7系统 OpenSSH和OpenSSL版本升级指南环境说明当前系统版本当前组件版本 现存安全漏洞升级目标版本升级准备工作OpenSSL升级步骤1. 下载和解压2. 编译安装3. 配置环境 OpenSSH升级步骤1. 下载和解压2. 编译安装3. 创建systemd服务配置4. 更新SSH配置文件5. 设置…...

使用 Comparable 和 Comparator 接口对集合排序

使用 Comparable 和 Comparator 接口对集合排序&#xff1a; 1. 使用 Comparable 接口&#xff1a; 当你希望一个类的对象能够按照某种自然顺序进行排序时&#xff0c;可以实现 Comparable 接口 并重写 compareTo() 方法。 实现步骤&#xff1a; 1.1 实现 Comparable<T&g…...

最新常见的图数据库对比,选型,架构,性能对比

图数据库排名 地址&#xff1a;https://db-engines.com/en/ranking/graphdbms 知识图谱查询语言 SPARQL、Cypher、Gremlin、PGQL 和 G-CORE 语法 / 语义 / 特性 SPARQL Cypher Gremlin PGQL G-CORE 图模式匹配查询 语法 CGP CGP CGP(无可选)1 CGP CGP 语义 子…...

混合合并两个pdf文件

混合两个pdf 1、在线免费交替和混合奇数和偶数PDF页面2、有什么软件把两个 PDF 交叉合并&#xff1f;3、pdfsam本地合并 如何Google翻译的原文和译文合并&#xff0c;&#xff08;沉浸式翻译效果相对较好&#xff09; 1、在线免费交替和混合奇数和偶数PDF页面 https://deftpd…...

OpenCV-Python实战(9)——滤波降噪

一、均值滤波器 cv2.blur() img cv2.blur(src*,ksize*,anchor*,borderType*)img&#xff1a;目标图像。 src&#xff1a;原始图像。 ksize&#xff1a;滤波核大小&#xff0c;&#xff08;width&#xff0c;height&#xff09;。 anchor&#xff1a;滤波核锚点&#xff0c…...

uniapp——微信小程序读取bin文件,解析文件的数据内容(三)

微信小程序读取bin文件内容 读取用户选择bin文件&#xff0c;并解析数据内容&#xff0c;分包发送给蓝牙设备&#xff1b; 文章目录 微信小程序读取bin文件内容读取文件读取内容返回格式 API文档&#xff1a; getFileSystemManager 关于App端读取bin文件&#xff0c;请查看&…...

Python 中常用的算法

1. 排序算法 用于将数据按特定顺序排列。 冒泡排序&#xff08;Bubble Sort&#xff09;选择排序&#xff08;Selection Sort&#xff09;插入排序&#xff08;Insertion Sort&#xff09;快速排序&#xff08;Quick Sort&#xff09;归并排序&#xff08;Merge Sort&#xf…...

xadmin后台首页增加一个导入数据按钮

xadmin后台首页增加一个导入数据按钮 效果 流程 1、在添加小组件中添加一个html页面 2、写入html代码 3、在urls.py添加导入数据路由 4、在views.py中添加响应函数html代码 <!DOCTYPE html> <html lang...

Kubernetes: NetworkPolicy 的实践应用

一、Network Policy 是什么,在云原生领域有和作用 Network Policy 是 Kubernetes 官方提出来的一种网络策略的规范&#xff0c;用户通过编写符合对应规范的规则来控制 k8s 集群内 L3 和 L4 层的网络流量。 NetworkPolicy 主要的功能就是实现在云原生领域的容器网络管控它给用…...

计算机体系结构期末复习3:GPU架构及控制流问题

目录 一、GPU设计思路 1.简化流水线、增加核数 2.单指令多线程&#xff08;SIMT&#xff09; 3.同时驻留大量线程 4.总思路&#xff1a;多线程单指令多线程 二、GPU的控制流问题 1.什么是控制流问题 2.怎么应对分支分歧 一、GPU设计思路 1.简化流水线、增加核数 2.单指…...

excel怎么删除右边无限列(亲测有效)

excel怎么删除右边无限列&#xff08;亲测有效&#xff09; 网上很多只用第1步的&#xff0c;删除了根本没用&#xff0c;还是存在&#xff0c;但是隐藏后取消隐藏却是可以的。 找到右边要删除的列的第一个空白列&#xff0c;选中整个列按“ctrlshift>(向右的小箭头)”&am…...

ChatGPT-4助力学术论文提升文章逻辑、优化句式与扩充内容等应用技巧解析。附提示词案例

目录 1.扩写&#xff08;expansion/paraphrasing&#xff09; 2.优化&#xff08;optimization&#xff09; 3.缩写&#xff08;optimization&#xff09; 4.提取关键词&#xff08;keyword extraction&#xff09; 5.短语转换&#xff08;phrase transformation&#xff…...

C++和OpenGL实现3D游戏编程【连载19】——着色器光照初步(平行光和光照贴图)(附源码)

1、本节要实现的内容 我们在前期的教程中,讨论了在即时渲染模式下的光照内容。但在我们后期使用着色器的核心模式下,会经常在着色器中使光照,我们这里就讨论一下着色器光照效果,以及光照贴图效果,同时这里知识会为后期的更多光照效果做一些铺垫。本节我们首先讨论冯氏光照…...

html+css网页制作 美食 美食网5个页面

htmlcss网页制作 美食 美食网5个页面 网页作品代码简单&#xff0c;可使用任意HTML辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#xff09;。 获取源码 1&#xff0…...

Mac 12.1安装tiger-vnc问题-routines:CRYPTO_internal:bad key length

背景&#xff1a;因为某些原因需要从本地mac连接远程linxu桌面查看一些内容&#xff0c;必须使用桌面查看&#xff0c;所以ssh无法满足&#xff0c;所以决定安装vnc客户端。 问题&#xff1a; 在mac上通过 brew install tiger-vnc命令安装, 但是报错如下&#xff1a; > D…...

遥感图像车辆检测-目标检测数据集

遥感图像车辆检测-目标检测数据集&#xff08;包括VOC格式、YOLO格式&#xff09; 数据集&#xff1a; 链接: https://pan.baidu.com/s/1XVlRTVWpXZFi6ZL_Xcs7Rg?pwdaa6g 提取码: aa6g 数据集信息介绍&#xff1a; 共有 1035 张图像和一一对应的标注文件 标注文件格式提供了…...

51c自动驾驶~合集43

我自己的原文哦~ https://blog.51cto.com/whaosoft/12930230 #ChatDyn 上交大最新ChatDyn&#xff1a;一句话操纵三维动态 理解和生成真实的三维虚拟世界是空间智能的核心。所生成的三维虚拟世界能够为自动驾驶、具身智能等AI系统提供高质量闭环仿真训练场&#xff0c;高效…...

随机变量是一个函数-如何理解

文章目录 一. 随机变量二. 随机变量是一个函数-栗子(一对一)1. 掷骰子的随机变量2. 掷骰子的随机变量&#xff08;求点数平方&#xff09;3. 抛硬币的随机变量4. 学生考试得分的随机变量 三. 随机变量是一个函数-理解(多对一) 一. 随机变量 随机变量就是定义在样本空间上的函数…...

云计算在医疗行业的应用

云计算在医疗行业的应用广泛而深入&#xff0c;为医疗服务带来了前所未有的变革。以下是对云计算在医疗行业应用的详细解析&#xff1a; ### 一、医疗数据共享与整合 云计算平台具有强大的数据存储和处理能力&#xff0c;使得医疗数据共享与整合成为可能。通过云计算平台&…...

Cursor提示词

你是一位经验丰富的项目经理&#xff0c;对于用户每一次提出的问题&#xff0c;都不急于编写代码&#xff0c;更多是通过深思熱虑、结构化的推理以产生高质量的回答&#xff0c;探索更多的可能方案&#xff0c;并从中寻找最佳方案。 约束 代码必须可以通过编译回答尽量使用中…...

C++ 设计模式:单例模式(Singleton Pattern)

链接&#xff1a;C 设计模式 链接&#xff1a;C 设计模式 - 享元模式 单例模式&#xff08;Singleton Pattern&#xff09;是创建型设计模式&#xff0c;它确保一个类只有一个实例&#xff0c;并提供一个全局访问点来访问这个实例。单例模式在需要全局共享资源或控制实例数量的…...

C++中生成0到180之间的随机数

在C中生成0到180之间的随机数&#xff0c;可以使用标准库中的和头文件。提供了rand()函数来生成随机数&#xff0c;而提供了time()函数来设置随机数生成的种子。这样每次运行程序时&#xff0c;生成的随机数序列都会不同。 以下是一个简单的示例代码&#xff0c;展示了如何生成…...

[.闲于修.]Autosar_UDS_笔记篇_ISO14229-1

前言&#xff1a;闲来无事&#xff0c;摸鱼无趣&#xff0c;准备细读一下14229&#xff0c;记录一些容易被忽略掉的内容 正文&#xff1a;&#xff08;以下数字代表章节&#xff09; 7、Application layer protocol 7.5.6 多个并发请求消息 常见的服务器实现在服务器中只有一…...

如何利用云计算进行灾难恢复?

云计算环境下的灾难恢复实践指南 天有不测风云&#xff0c;企业的IT系统也一样&#xff0c;我见过太多因为没有做好灾备而吃大亏的案例。今天就和大家聊聊如何用云计算来做灾难恢复。 一个惊心动魄的真实案例&#xff1a;某电商平台的主数据中心因为市政施工不小心挖断了光纤…...

Redis - 1 ( 7000 字 Redis 入门级教程 )

一&#xff1a; Redis 1.1 Redis 简介 Redis 是一种基于键值对&#xff08;key-value&#xff09;的 NoSQL 数据库&#xff0c;与其他键值对数据库不同&#xff0c;Redis 的值可以是多种数据结构和算法的组合&#xff0c;如字符串&#xff08;string&#xff09;、哈希&#…...

[羊城杯 2024]不一样的数据库_2

题目描述&#xff1a; 压缩包6 (1).zip需要解压密码&#xff1a; 尝试用ARCHPR工具爆破一下&#xff1a; &#xff08;字典可自行在github上查找&#xff09; 解压密码为&#xff1a;753951 解压得到13.png和Kee.kdbx文件&#xff1a; 二维码图片看上去只缺了正常的三个角&…...

租赁系统的数字化转型与高效管理新模式分析

内容概要 在当今瞬息万变的市场环境中&#xff0c;租赁系统的数字化转型显得尤为重要。信息技术的迅猛发展不仅改变了我们的生活方式&#xff0c;也迫使企业重新审视其运营模式。为了顺应这一潮流&#xff0c;租赁系统亟需通过高效管理新模式来提升运营效率&#xff0c;从而保…...

Selenium+Java(21):Jenkins发送邮件报错Not sent to the following valid addresses解决方案

问题现象 小月妹妹近期在做RobotFrameWork自动化测试,并且使用Jenkins发送测试邮件的时候,发现报错Not sent to the following valid addresses,明明各个配置项看起来都没有问题,但是一到邮件发送环节,就是发送不出去,而且还不提示太多有用的信息,急的妹妹脸都红了,于…...

【每日学点鸿蒙知识】文字识别、快捷登录、输入法按钮监听、IDE自动换行、资产访问等

【每日学点鸿蒙知识】24.09.07 1、API使用&#xff1a; hms.ai.ocr.textRecognition&#xff08;文字识别&#xff09;&#xff1f; 需要接入API文档https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/core-vision-text-recognition-api-V5中的文字识别…...

LabVIEW化工实验室设备故障实时监测

化工实验室中&#xff0c;各类设备的运行状态直接影响实验的精度与安全性。特别是重要分析仪器的突发故障&#xff0c;可能导致实验中断或数据失效。为了实现设备运行状态的实时监控与故障快速响应&#xff0c;本文提出了一套基于LabVIEW的解决方案&#xff0c;通过多参数采集、…...

小程序学习05——uniapp路由和菜单配置

目录 一、路由 二、如何管理页面及路由&#xff1f; 三、pages.json 页面路由 四、 tabBar 一、路由 路由&#xff1a;在前端&#xff0c;往往指代用不同地址请求不同页面&#xff0c;决定了用户如何在应用的不同页面之间导航。 菜单&#xff1a;对于每个路径&#xff08;…...

漏洞分析 | Apache Struts文件上传漏洞(CVE-2024-53677)

漏洞概述 Apache Struts是美国阿帕奇&#xff08;Apache&#xff09;基金会的一个开源项目&#xff0c;是一套用于创建企业级Java Web应用的开源MVC框架。 近期&#xff0c;网宿安全演武实验室监测到Apache Struts在特定条件下&#xff0c;存在文件上传漏洞&#xff08;网宿评…...

【VBA】EXCEL - VBA 遍历工作表的 5 种方法,以及注意事项

目录 1. 遍历单列数据并赋值 2. 遍历整个工作表的数据区域并赋值 3. 遍历指定范围的数据并赋值 4. 遍历多列数据并赋值 5. 遍历所有工作表中的数据并赋值 注意事项&#xff1a; 1. 遍历单列数据并赋值 Sub UpdateColumnData()Dim ws As WorksheetSet ws ThisWorkbook.S…...

CSS浮动

浮动 可以让块级元素待在一行&#xff0c;紧挨着&#xff0c;没有空格 float&#xff1a;left 浮动的元素会脱离正常的文档系统&#xff0c;像浮云一样飘起来浮动元素后面的正常元素会自动补位浮动元素会被父元素的宽高所束缚&#xff0c;所以不算完全的脱离文档流当浮动元素…...

gitlab 还原合并请求

事情是这样的&#xff1a; 菜鸡从 test 分支切了个名为 pref-art 的分支出来&#xff0c;发布后一机灵&#xff0c;发现错了&#xff0c;于是在本地用 git branch -d pref-art 将该分支删掉了。之后切到了 prod 分支&#xff0c;再切出了一个相同名称的 pref-art 分支出来&…...

【GPT】Coze使用开放平台接口-【8】创建应用

coze 可以用来创建简单的应用啦&#xff0c;这样测试起来会比原本的 Agent 更加方便&#xff0c;我们来看看如何创建一个“语音Real不Real”的应用。这个应用就是来检测语音是否是伪造的&#xff0c;克隆或者是合成的。先看下原本 Agent 的样子&#xff1a; 深度伪造语音检测&a…...

海外盲盒系统开发,助力企业全球化发展

近几年来&#xff0c;在海外市场中&#xff0c;盲盒已经成为了一种新的时尚单品&#xff0c;深受东南亚等海外消费者的喜爱。同时&#xff0c;泡泡玛特在海外的成功也为国内企业提供了发展机遇&#xff0c;盲盒出海具有广阔的发展前景&#xff01;‌ 随着信息技术的快速发展&a…...