Unity图文混排EmojiText的使用方式和注意事项

                ​​​​​​​  效果演示:

使用方式:

1、导入表情

2、设置图片格式

3、生成表情图集

4、创建/修改目标材质球

5、测试

修复换行问题

修复前:

修复后:

修复代码:

组件扩展

1、右键扩展

2、组件归类:

注意事项

文章引用:


EmojiText组件代码来源工程地址:https://github.com/zouchunyi/EmojiText

效果演示:

使用方式:

1、导入表情

将表情图片素材(png格式)导入到Unity工程中的这个目录中:Assets/Emoji/Input,目录可以按需更换。

注意表情图片的尺寸必须一致,命名规范:纯字母.png或 纯字母_数字.png,例:a.png, b_0.png,b_1.png。

同一个表情的序列帧图片,以_数字结尾。

2、设置图片格式

设置图片格式为Default,设置Non-Power of 2(2的n次方)为ToNearest,勾选Read/Write Enabled。最后点击Apply按钮。

3、生成表情图集

点击菜单EmojiText/Build Emoji后,会按照EmojiBuilder脚本中的默认值进行创建图集保存数据,为了方便操作在这里扩展成一个UnityEditor窗口。

/*Description:Create the Atlas of emojis and its data texture.How to use?1)Put all emojies in Asset/Framework/Resource/Emoji/Input.Multi-frame emoji name format : Name_Index.png , Single frame emoji format: Name.png2)Excute EmojiText->Build Emoji from menu in Unity.3)It will outputs two textures and a txt in Emoji/Output.Drag emoji_tex to "Emoji Texture" and emoji_data to "Emoji Data" in UGUIEmoji material.4)Repair the value of "Emoji count of every line" base on emoji_tex.png.5)It will auto copys emoji.txt to Resources, and you can overwrite relevant functions base on your project.Author:zouchunyiE-mail:zouchunyi@kingsoft.com
*/
using System;
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using System.IO;
public class EmojiBuilder : EditorWindow  {private static string OutputPath = "Assets/Emoji/Output/";private static string InputPath = "Assets/Emoji/Input/";private const string CopyTargetPath = "Assets/Resources/emoji.txt";private static readonly Vector2[] AtlasSize = new Vector2[]{new Vector2(32,32),new Vector2(64,64),new Vector2(128,128),new Vector2(256,256),new Vector2(512,512),new Vector2(1024,1024),new Vector2(2048,2048)};struct EmojiInfo{public string key;public string x;public string y;public string size;}private static int EmojiSize = 32;//the size of emoji.[MenuItem("EmojiText/Build Emoji Wnd")]public static void BuildEmojiWnd(){GetWindow<EmojiBuilder>();}private void OnGUI(){InputPath = EditorGUILayout.TextField("表情散图存放路径", InputPath);OutputPath = EditorGUILayout.TextField("表情图集生成路径", OutputPath);EditorGUILayout.HelpBox("注意:每个表情图片尺寸需要统一。",MessageType.Warning);EmojiSize = EditorGUILayout.IntField("单个表情图尺寸", EmojiSize);if (GUILayout.Button("生成表情图集")) {BuildEmoji (); }}// [MenuItem("EmojiText/Build Emoji")]public static void BuildEmoji(){// List<char> keylist = new List<char> ();// for(int i = 0; i<100; i++)// {//  keylist.Add(i.ToString());// }// for (int i = 48; i <= 57; i++) {//  keylist.Add (System.Convert.ToChar(i));//0-9// }// for (int i = 65; i <= 90; i++) {//  keylist.Add (System.Convert.ToChar(i));//A-Z// }// for (int i = 97; i <= 122; i++) {//  keylist.Add (System.Convert.ToChar(i));//a-z// }//search all emojis and compute they frames.Dictionary<string,int> sourceDic = new Dictionary<string,int> ();string[] files = Directory.GetFiles (Application.dataPath.Replace("Assets", "") + InputPath,"*.png");for (int i = 0; i < files.Length; i++) {string[] strs = files [i].Split ('/');string[] strs2 = strs [strs.Length - 1].Split ('.');string filename = strs2 [0];string[] t = filename.Split('_');string id = t [0];if (sourceDic.ContainsKey(id)) {sourceDic[id]++;} else {sourceDic.Add (id, 1);}}//create the directory if it is not exist.if (!Directory.Exists (OutputPath)) {Directory.CreateDirectory (OutputPath);}   Dictionary<string,EmojiInfo> emojiDic = new Dictionary<string, EmojiInfo> ();int totalFrames = 0;foreach (int value in sourceDic.Values) {totalFrames += value;}Vector2 texSize = ComputeAtlasSize (totalFrames);Texture2D newTex = new Texture2D ((int)texSize.x, (int)texSize.y, TextureFormat.ARGB32, false);Texture2D dataTex = new Texture2D ((int)texSize.x / EmojiSize, (int)texSize.y / EmojiSize, TextureFormat.ARGB32, false);int x = 0;int y = 0;int keyindex = 0;foreach (string key in sourceDic.Keys) {for (int index = 0; index < sourceDic[key]; index++) {string path = InputPath + key;if (sourceDic[key] == 1) {path += ".png";} else {path += "_" + (index + 1).ToString() + ".png";}Texture2D asset = AssetDatabase.LoadAssetAtPath<Texture2D> (path);Color[] colors = asset.GetPixels (0); for (int i = 0; i < EmojiSize; i++) {for (int j = 0; j < EmojiSize; j++) {newTex.SetPixel (x + i, y + j, colors [i + j * EmojiSize]);}}string t = System.Convert.ToString (sourceDic [key] - 1, 2);float r = 0, g = 0, b = 0;if (t.Length >= 3) {r = t [2] == '1' ? 0.5f : 0;g = t [1] == '1' ? 0.5f : 0;b = t [0] == '1' ? 0.5f : 0;} else if (t.Length >= 2) {r = t [1] == '1' ? 0.5f : 0;g = t [0] == '1' ? 0.5f : 0;} else {r = t [0] == '1' ? 0.5f : 0;}dataTex.SetPixel (x / EmojiSize, y / EmojiSize, new Color (r, g, b, 1));if (! emojiDic.ContainsKey (key)) {EmojiInfo info;// if (keyindex < keylist.Count)// {//  info.key = "[" + char.ToString(keylist[keyindex]) + "]";// }else// {//  info.key = "[" + char.ToString(keylist[keyindex / keylist.Count]) + char.ToString(keylist[keyindex % keylist.Count]) + "]";// }info.key = "[" + keyindex + "]";info.x = (x * 1.0f / texSize.x).ToString();info.y = (y * 1.0f / texSize.y).ToString();info.size = (EmojiSize * 1.0f / texSize.x).ToString ();emojiDic.Add (key, info);keyindex ++;}x += EmojiSize;if (x >= texSize.x) {x = 0;y += EmojiSize;}}}byte[] bytes1 = newTex.EncodeToPNG ();string outputfile1 = OutputPath + "emoji_tex.png";File.WriteAllBytes (outputfile1, bytes1);byte[] bytes2 = dataTex.EncodeToPNG ();string outputfile2 = OutputPath + "emoji_data.png";File.WriteAllBytes (outputfile2, bytes2);using (StreamWriter sw = new StreamWriter (OutputPath + "emoji.txt",false)) {sw.WriteLine ("Name\tKey\tFrames\tX\tY\tSize");foreach (string key in emojiDic.Keys) {sw.WriteLine ("{" + key + "}\t" + emojiDic[key].key + "\t" + sourceDic[key] + "\t" + emojiDic[key].x + "\t" + emojiDic[key].y + "\t" + emojiDic[key].size);}sw.Close ();}File.Copy (OutputPath + "emoji.txt",CopyTargetPath,true);AssetDatabase.Refresh ();FormatTexture ();EditorUtility.DisplayDialog ("生成成功", "生成表情图集成功!", "确定");}private static Vector2 ComputeAtlasSize(int count){long total = count * EmojiSize * EmojiSize;for (int i = 0; i < AtlasSize.Length; i++) {if (total <= AtlasSize [i].x * AtlasSize [i].y) {return AtlasSize [i];}}return Vector2.zero;}private static void FormatTexture() {TextureImporter emojiTex = AssetImporter.GetAtPath (OutputPath + "emoji_tex.png") as TextureImporter;emojiTex.filterMode = FilterMode.Point;emojiTex.mipmapEnabled = false;emojiTex.sRGBTexture = true;emojiTex.alphaSource = TextureImporterAlphaSource.FromInput;emojiTex.textureCompression = TextureImporterCompression.Uncompressed;emojiTex.SaveAndReimport ();TextureImporter emojiData = AssetImporter.GetAtPath (OutputPath + "emoji_data.png") as TextureImporter;emojiData.filterMode = FilterMode.Point;emojiData.mipmapEnabled = false;emojiData.sRGBTexture = false;emojiData.alphaSource = TextureImporterAlphaSource.None;emojiData.textureCompression = TextureImporterCompression.Uncompressed;emojiData.SaveAndReimport ();}
}

生成成功后可以在“表情图集生成路径”中看到有三个文件。

其中emoji文本文件记录了,当前生成的图集中每个表情的数据信息。

该文件会在生成的时候拷贝到Resources目录,该地址可以通过脚本中CopyTargetPath属性值进行指定。

4、创建/修改目标材质球

原工程默认会自带一个材质球“UGUIEmoji”,目标位于材质球“Material”文件夹中,如果灭有可以手动创建。右键Shader文件夹中的“UI-EmojiFont”文件可以直接创建目标材质球。也可以创建出来材质球后手动指定材质球的Shader。

将生成好的emoji_data和emoji_tex分别拖放到材质球对应的属性中。

因为生成的图集“emoji_tex”的每一行是4个表情,所以设置Emoji count of every line为4,FrameSpeed是每秒播放序列帧数量,可根据实际情况调整。

5、测试

创建一个空对象,挂载“EmojiText”脚本组件,在输入文本内容“[0]你好[1]”,给组件添加改好的材质球,即可看到效果。

修复换行问题

修复前:

修复后:

问题修复需要改动“EmojiText”脚本。修复工程源码来源:https://github.com/ry02/EmojiText

修复代码:
// Textは自動改行が入ると、改行コードの位置にもvertsの中に頂点情報が追加されるが、
// 自動改行が入らないと、改行コードのための頂点情報は無いので、Indexを調整する
if (emojiDic.Count > 0)
{MatchCollection newLines = Regex.Matches(emojiText, "\\n");// TextのRect範囲外は行(lineCount)にならないので、全文字が表示されている(characterCount)かも確認する。if (cachedTextGenerator.lineCount == newLines.Count + 1 && emojiText.Length < cachedTextGenerator.characterCount){// 絵文字があり、自動改行が入っていないので、indexを改行コードの数だけ調整するDictionary<int, EmojiInfo> emojiDicReplace = new Dictionary<int, EmojiInfo>();foreach (var ed in emojiDic){int index = ed.Key;int offset = 0;foreach (Match nl in newLines){if (nl.Index < index){offset -= 1;}}emojiDicReplace.Add(index + offset, ed.Value);}emojiDic = emojiDicReplace;}
}

修复后的EmojiText源代码:

using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
using System.Text.RegularExpressions;
public class EmojiText : Text
{private const float ICON_SCALE_OF_DOUBLE_SYMBOLE = 0.7f;public override float preferredWidth =>cachedTextGeneratorForLayout.GetPreferredWidth(emojiText, GetGenerationSettings(rectTransform.rect.size)) /pixelsPerUnit;public override float preferredHeight =>cachedTextGeneratorForLayout.GetPreferredHeight(emojiText, GetGenerationSettings(rectTransform.rect.size)) /pixelsPerUnit;private string emojiText => Regex.Replace(text, "\\[[a-z0-9A-Z]+\\]", "%%");private static Dictionary<string, EmojiInfo> m_EmojiIndexDict = null;struct EmojiInfo{public float x;public float y;public float size;}readonly UIVertex[] m_TempVerts = new UIVertex[4];protected override void OnPopulateMesh(VertexHelper toFill){if (font == null){return;}if (m_EmojiIndexDict == null){m_EmojiIndexDict = new Dictionary<string, EmojiInfo>();//load emoji data, and you can overwrite this segment code base on your project.TextAsset emojiContent = Resources.Load<TextAsset>("emoji");string[] lines = emojiContent.text.Split('\n');for (int i = 1; i < lines.Length; i++){if (!string.IsNullOrEmpty(lines[i])){string[] strs = lines[i].Split('\t');EmojiInfo info;info.x = float.Parse(strs[3]);info.y = float.Parse(strs[4]);info.size = float.Parse(strs[5]);m_EmojiIndexDict.Add(strs[1], info);}}}Dictionary<int, EmojiInfo> emojiDic = new Dictionary<int, EmojiInfo>();if (supportRichText){int nParcedCount = 0;//[1] [123] 替换成#的下标偏移量          int nOffset = 0;MatchCollection matches = Regex.Matches(text, "\\[[a-z0-9A-Z]+\\]");for (int i = 0; i < matches.Count; i++){EmojiInfo info;if (m_EmojiIndexDict.TryGetValue(matches[i].Value, out info)){emojiDic.Add(matches[i].Index - nOffset + nParcedCount, info);nOffset += matches[i].Length - 1;nParcedCount++;}}}// We don't care if we the font Texture changes while we are doing our Update.// The end result of cachedTextGenerator will be valid for this instance.// Otherwise we can get issues like Case 619238.m_DisableFontTextureRebuiltCallback = true;Vector2 extents = rectTransform.rect.size;var settings = GetGenerationSettings(extents);cachedTextGenerator.Populate(emojiText, settings);Rect inputRect = rectTransform.rect;// get the text alignment anchor point for the text in local spaceVector2 textAnchorPivot = GetTextAnchorPivot(alignment);Vector2 refPoint = Vector2.zero;refPoint.x = Mathf.Lerp(inputRect.xMin, inputRect.xMax, textAnchorPivot.x);refPoint.y = Mathf.Lerp(inputRect.yMin, inputRect.yMax, textAnchorPivot.y);// Apply the offset to the verticesIList<UIVertex> verts = cachedTextGenerator.verts;float unitsPerPixel = 1 / pixelsPerUnit;int vertCount = verts.Count;// We have no verts to process just return (case 1037923)if (vertCount <= 0){toFill.Clear();return;}// Textは自動改行が入ると、改行コードの位置にもvertsの中に頂点情報が追加されるが、// 自動改行が入らないと、改行コードのための頂点情報は無いので、Indexを調整するif (emojiDic.Count > 0){MatchCollection newLines = Regex.Matches(emojiText, "\\n");// TextのRect範囲外は行(lineCount)にならないので、全文字が表示されている(characterCount)かも確認する。if (cachedTextGenerator.lineCount == newLines.Count + 1 && emojiText.Length < cachedTextGenerator.characterCount){// 絵文字があり、自動改行が入っていないので、indexを改行コードの数だけ調整するDictionary<int, EmojiInfo> emojiDicReplace = new Dictionary<int, EmojiInfo>();foreach (var ed in emojiDic){int index = ed.Key;int offset = 0;foreach (Match nl in newLines){if (nl.Index < index){offset -= 1;}}emojiDicReplace.Add(index + offset, ed.Value);}emojiDic = emojiDicReplace;}}Vector2 roundingOffset = new Vector2(verts[0].position.x, verts[0].position.y) * unitsPerPixel;roundingOffset = PixelAdjustPoint(roundingOffset) - roundingOffset;toFill.Clear();if (roundingOffset != Vector2.zero){for (int i = 0; i < vertCount; ++i){int tempVertsIndex = i & 3;m_TempVerts[tempVertsIndex] = verts[i];m_TempVerts[tempVertsIndex].position *= unitsPerPixel;m_TempVerts[tempVertsIndex].position.x += roundingOffset.x;m_TempVerts[tempVertsIndex].position.y += roundingOffset.y;if (tempVertsIndex == 3){toFill.AddUIVertexQuad(m_TempVerts);}}}else{for (int i = 0; i < vertCount; ++i){EmojiInfo info;int index = i / 4;if (emojiDic.TryGetValue(index, out info)){//compute the distance of '[' and get the distance of emoji //计算2个%%的距离float emojiSize = 2 * (verts[i + 1].position.x - verts[i].position.x) *ICON_SCALE_OF_DOUBLE_SYMBOLE;float fCharHeight = verts[i + 1].position.y - verts[i + 2].position.y;float fCharWidth = verts[i + 1].position.x - verts[i].position.x;float fHeightOffsetHalf = (emojiSize - fCharHeight) * 0.5f;float fStartOffset = emojiSize * (1 - ICON_SCALE_OF_DOUBLE_SYMBOLE);m_TempVerts[3] = verts[i]; //1m_TempVerts[2] = verts[i + 1]; //2m_TempVerts[1] = verts[i + 2]; //3m_TempVerts[0] = verts[i + 3]; //4m_TempVerts[0].position += new Vector3(fStartOffset, -fHeightOffsetHalf, 0);m_TempVerts[1].position +=new Vector3(fStartOffset - fCharWidth + emojiSize, -fHeightOffsetHalf, 0);m_TempVerts[2].position += new Vector3(fStartOffset - fCharWidth + emojiSize, fHeightOffsetHalf, 0);m_TempVerts[3].position += new Vector3(fStartOffset, fHeightOffsetHalf, 0);m_TempVerts[0].position *= unitsPerPixel;m_TempVerts[1].position *= unitsPerPixel;m_TempVerts[2].position *= unitsPerPixel;m_TempVerts[3].position *= unitsPerPixel;float pixelOffset = emojiDic[index].size / 32 / 2;m_TempVerts[0].uv1 = new Vector2(emojiDic[index].x + pixelOffset, emojiDic[index].y + pixelOffset);m_TempVerts[1].uv1 = new Vector2(emojiDic[index].x - pixelOffset + emojiDic[index].size,emojiDic[index].y + pixelOffset);m_TempVerts[2].uv1 = new Vector2(emojiDic[index].x - pixelOffset + emojiDic[index].size,emojiDic[index].y - pixelOffset + emojiDic[index].size);m_TempVerts[3].uv1 = new Vector2(emojiDic[index].x + pixelOffset,emojiDic[index].y - pixelOffset + emojiDic[index].size);toFill.AddUIVertexQuad(m_TempVerts);i += 4 * 2 - 1;}else{int tempVertsIndex = i & 3;m_TempVerts[tempVertsIndex] = verts[i];m_TempVerts[tempVertsIndex].position *= unitsPerPixel;if (tempVertsIndex == 3){toFill.AddUIVertexQuad(m_TempVerts);}}}}m_DisableFontTextureRebuiltCallback = false;}
}

组件扩展

1、右键扩展

在使用中为了方便的创建对象,如同创建Text时的右键菜单,这时候我们可以扩展一下脚本。

新建一个脚本 “EmojiMenu”,添加如下代码:

private static Transform FindParent()
{// 获取当前选择的对象,并检索是否符合条件var transform = Selection.activeTransform;if (transform == null){var canvas = FindObjectOfType<Canvas>();if (canvas){return canvas.transform;}}else if (transform.GetComponentInParent<Canvas>()){return transform;}// 创建一个Canvas对象var gameObject = new GameObject("UICanvas");if (transform != null){gameObject.transform.SetParent(transform);}gameObject.AddComponent<Canvas>();gameObject.AddComponent<CanvasScaler>();gameObject.AddComponent<GraphicRaycaster>();return gameObject.transform;
}
[MenuItem("GameObject/UI/Emoji Text")]
public static void AddEmojiText(MenuCommand menuCommand)
{var child = new GameObject("Emoji Text", typeof(EmojiText));RectTransform rectTransform = child.GetComponent<RectTransform>();rectTransform.SetParent(FindParent());rectTransform.sizeDelta = new Vector2(160, 30);rectTransform.localPosition = Vector3.zero;rectTransform.localRotation = Quaternion.identity;rectTransform.localScale = Vector3.one;
}
2、组件归类:

在“EmojiText”类前面添加即可实现,展开组件菜单的UI项,可以找到当前类型。

[AddComponentMenu("UI/EmojiText", 100)]

注意事项

1、存在换行时或者一条字符串中有多个表情时,添加空格会导致文本错乱!!!

2、在使用EmojiText组件时,父节点中如果存在Canvas,请注意Canvas的Additional Shader Channels 属性是否选择了TexCoord1,如果没有选择请勾选该选项,否则会导致图文混排显示异常。

文章引用:

1、GitHub:zouchunyi/EmojiText

2、GitHub:ry02/EmojiText

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

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

相关文章

南京信工一班IP(2)

第六章&#xff0c;BGP—边界网关协议 自治系统—AS ​ 定义&#xff1a;由一个单一的机构或组织所管理的一系列IP网络及其设备所构成的集合。 ​ AS的来源&#xff1a; 整个网络规模过大&#xff0c;会导致路由信息收敛速度过慢&#xff0c;设备对相同目标认知不同。AS之间…

LeetCode题目104: 二叉树的最大深度(递归\迭代\层序遍历\尾递归优化\分治法实现 )

❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容&#xff0c;和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣&#xff01; 推荐&#xff1a;数据分析螺丝钉的首页 格物致知 终身学习 期待您的关注 导航&#xff1a; LeetCode解锁100…

Android system property运作流程源码分析

一.序 前文分析了build.prop这个系统属性文件的生成&#xff0c;每个属性都有一个名称和值&#xff0c;他们都是字符串格式。属性被大量使用在Android系统中&#xff0c;用来记录系统设置或进程之间的信息交换。属性是在整个系统中全局可见的。每个进程可以get/set属性&#x…

【IMX6ULL项目】IMX6ULL下Linux实现产测工具框架

电子产品量产测试与烧写工具。这是一套软件&#xff0c;用在我们的实际生产中&#xff0c; 有如下特点&#xff1a; 1.简单易用&#xff1a; 把这套软件烧写在 SD 卡上&#xff0c;插到 IMX6ULL 板子里并启动&#xff0c;它就会自动测试各个模块、烧写 EMMC 系统。 工人只要按…

数据库系统理论——关系数据库标准语言SQL

文章目录 一、数据定义1、基本表的定义、删除与修改2、索引的建立于删除&#xff08;了解&#xff09; 二、数据查询&#xff08;会其中一种&#xff09;1、单表查询&#xff08;1&#xff09;这里出现重复元组&#xff0c;怎么处理&#xff1f;&#xff1f;&#xff08;2&…

渗透测试-信息收集

网络安全信息收集是网络安全领域中至关重要的一环&#xff0c;它涉及到对目标系统、网络或应用进行全面而细致的信息搜集和分析。这一过程不仅有助于理解目标网络的结构、配置和潜在的安全风险&#xff0c;还能为后续的渗透测试、风险评估和安全加固提供有力的支持。 在网络安…

单调栈问题

原理 单调栈的核心原理是&#xff1a;在栈内保持元素的单调性&#xff08;递增或递减&#xff09; 单调递增栈&#xff1a; 用于处理“下一个更小的元素”问题。当新元素比栈顶元素小或等于时&#xff0c;直接入栈&#xff1b;否则&#xff0c;一直从栈顶弹出元素&#xff0c…

信息系统项目管理师0102:可行性研究的内容(7项目立项管理—7.2项目可行性研究—7.2.1可行性研究的内容)

点击查看专栏目录 文章目录 7.2项目可行性研究7.2.1可行性研究的内容1.技术可行性分析2.经济可行性分析3.社会效益可行性分析4.运行环境可行性分析5.其他方面的可行性分析记忆要点总结7.2项目可行性研究 可行性研究是在项目建议书被批准后,从技术、经济、社会和人员等方面的条…

在STM32中用寄存器方式点亮流水灯

文章目录 实验资料一、对寄存器的理解1.通俗认识寄存器2.深入了解寄存器&#xff08;1&#xff09;端口配置低寄存器&#xff08;配置0到7引脚的寄存器&#xff09;&#xff08;2&#xff09;端口配置高寄存器&#xff08;配置8到15引脚&#xff09; 3.GPIO口的功能描述 二、配…

【网络】网络基础

目录 一、前言 1.计算机网络背景 2.认识协议 二、网络协议初识 1.OSI七层模型 2.TCP/IP五层(或四层)模型 3.网络传输基本流程 4.数据包封装和分用 5.网络中的地址管理 1.IP地址 2.MAC地址 一、前言 1.计算机网络背景 网络之前&#xff0c;我们所有在电脑上的操作都是…

LeetCode题练习与总结:二叉树的中序遍历--94

一、题目描述 给定一个二叉树的根节点 root &#xff0c;返回 它的 中序 遍历 。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,3,2]示例 2&#xff1a; 输入&#xff1a;root [] 输出&#xff1a;[]示例 3&#xff1a; 输入&#xff1a;roo…

Github学习

1.Git与Github 区别: Git是一个分布式版本控制系统&#xff0c;简单的说就是一个软件&#xff0c;用于记录一个或若干个文件内容变化&#xff0c;以便将来查阅特点版本修订情况的软件。 Github是一个为用户提高Git服务的网站&#xff0c;简单说就是一个可以放代码的地方。Gi…

韩顺平0基础学Java——第10天

p202-233 类与对象&#xff08;第七章&#xff09; 成员方法 person类中的speak方法&#xff1a; 1.public表示方法是公开的 2.void表示方法没有返回值 3.speak&#xff08;&#xff09;中&#xff0c;speak表示方法名&#xff0c;括号是形参列表。 4.大括号为方法体&am…

重塑数据架构:云器Lakehouse如何简化组装式架构实现性能与成本的精益平衡

导读本文将介绍云器科技自研的 Lakehouse 产品。通过本次分享&#xff0c;您将了解云器 Lakehouse 产品特性&#xff0c;了解一体化数据平台如何提升数据处理和数据分析的效率&#xff0c;使之更轻松、更简洁、更高效&#xff0c;了解增量计算如何做到平衡数据新鲜度、查询性能…

DE2-115串口通信

目录 一、 内容概要二、 Hello Nios-II2.1 Nios-II编程2.1.1 硬件Ⅰ 搭建环境Ⅱ 编写代码 2.1.2 软件2.1.3 烧录Ⅰ硬件Ⅱ 软件 2.2 verilog编程 三、 心得体会 一、 内容概要 分别用Verilog和Nios软件编程, 实现DE2-115开发板串口输出“Hello Nios-II”字符到笔记本电脑串口助…

【Shell】shell编程之循环语句

目录 1.for循环 例题 2.while循环 例题 3.until循环 1.for循环 读取不同的变量值&#xff0c;用来逐个执行同一组命令 for 变量 in 取值列表 do 命令序列 done [rootlocalhost ~]# for i in 1 2 3 > do > echo "第 $i 次跳舞" > done 第 1 次跳舞 第 …

使用Pycharm编写Python程序时对基本类结构中方法的重写的两种初步操作方式

使用Pycharm编写Python程序时对基本类结构中方法的重写的两种初步操作方式 Python和其他一些高级面向对象的编程语言中&#xff0c;子类可继承父类中的方法&#xff0c;而不需要重新编写相同的方法。但有时子类并不想原封不动地继承父类的方法&#xff0c;而是想作一定的修改&…

闲来装个虚拟机Ubuntu24.04和硬盘分区及挂载

简述 最近ubuntu出新版本了&#xff0c;ubuntu24.04&#xff0c; 俗称高贵食蚁兽。5年前进行Android或者linux开发基本是在windows下的虚拟机中进行。目前&#xff0c;虽然物质基础提高了&#xff0c;功能有独立进行编译、代码管理的服务器了。可以通过ssh登录&#xff0c;但是…

【C++11】C++11类与模板语法的完善

目录 一&#xff0c;新的类功能 1-1&#xff0c;默认成员函数 1-2&#xff0c;强制生成关键字 二&#xff0c;可变参数模板 2-1&#xff0c;模板参数包 2-2&#xff0c;STL容器empalce的相关接口 一&#xff0c;新的类功能 1-1&#xff0c;默认成员函数 C11之前的类中有…

Tomcat添加服务以及设置开机自启

下载地址连接 Index of /dist/tomcat&#x1f453; 注意点&#xff1a;不要出现中文路径 #环境变量 CATALINA_HOMED:\apache-tomcat-7.0.62 TOMCAT_HOMED:\apache-tomcat-7.0.62 JAVA_HOMED:\tool\jdk1.8.0_111 PATH%CATALINA_HOME%\bin;%CATALINA_HOME%\lib;%CATALINA_HOME%\…