[MAUI]写一个跨平台富文本编辑器

news/2024/2/28 7:30:00

文章目录

  • 原理
  • 创建编辑器
    • 定义
    • 实现复合样式
      • 选择范围
      • 字号
      • 字体颜色与背景色
      • 字体下划线
      • 字体加粗与斜体
  • 序列化和反序列化
    • 跨平台实现
    • 集成至编辑器
  • 创建控件
  • 使用控件
  • 最终效果
  • 已知问题
  • 项目地址

富文本编辑器是一种所见即所得(what you see is what you get 简称 WYSIWYG)文本编辑器,用户在编辑器中输入内容和所做的样式修改,都会直接反映在编辑器中。

在Web端常见的有Quill、TinyMCE这些开源免费的富文本编辑器,而目前.NET MAUI方面没有类似的富文本编辑器可以免费使用。

使用.NET MAUI实现一个富文本编辑器并不难,今天就来写一个

在这里插入图片描述

使用.NET MAU实现跨平台支持,本项目可运行于Android、iOS平台。由于篇幅本文只展示Android平台的代码。

原理

.NET MAUI提供了编辑器控件,允许输入和编辑多行文本,虽然提供了字号,字体,颜色等控件属性,但我们无法为每个字符设置样式。我们将通过原生控件提供的范围选择器实现这一功能。

.NET MAUI提供了Handler的跨平台特性,我们将利用Handler实现所见即所得内容编辑器组件。这篇博文介绍了如何用Handler实现自定义跨平台控件,请阅读[MAUI程序设计] 用Handler实现自定义跨平台控件

在各平台中,我们将使用原生控件实现所见即所得的内容编辑器

  • Android使用SpannableString设置文本的复合样式,可以查看https://www.cnblogs.com/jisheng/archive/2013/01/10/2854088.html

  • iOS使用NSAttributeString设置文本的复合样式,可以参考https://blog.csdn.net/weixin_44544690/article/details/124154949

创建编辑器

新建.NET MAUI项目,命名RichTextEditor

在Controls目录中创建WysiwygContentEditor,继承自Editor,用于实现所见即所得的内容编辑器

构造函数中注册HandlerChanged和HandlerChanging事件


public class WysiwygContentEditor : Editor
{public WysiwygContentEditor(){HandlerChanged+=WysiwygContentEditor_HandlerChanged;HandlerChanging+=WysiwygContentEditor_HandlerChanging;}}

在HandlerChanged事件中,获取Handler对象,通过它访问虚拟视图和本机视图。

private void WysiwygContentEditor_HandlerChanged(object sender, EventArgs e)
{var handler = Handler;if (handler != null){}
}

android端原生控件为AppCompatEditText,iOS端原生控件为UITextView

//Android
var platformView = handler.PlatformView as AppCompatEditText;
//iOS
var platformView = handler.PlatformView as UITextView;

不同平台的代码,通过.Net6的条件编译实现,有关条件编译的详细信息,请参考官方文档。这次实现的是Android和iOS平台,所以在代码中条件编译语句如下

#if ANDROID//android codes
...#endif#if IOS//iOS codes
...#endif

定义

定义StyleType枚举,用于控件可以处理的文本样式更改请求类型。

  • underline:字体下划线
  • italic:字体斜体
  • bold:字体加粗
  • backgoundColor:字体背景色
  • foregroundColor:字体前景色
  • size:字体大小
public enum StyleType
{underline, italic, bold, backgoundColor, foregroundColor, size
}

以及StyleArgs类,用于传递样式变更请求的参数

public class StyleArgs : EventArgs
{public StyleType Style;public string Params;public StyleArgs(StyleType style, string @params = null){Style = style;Params=@params;}
}

定义SelectionArgs类,用于传递选择范围变更请求的参数

public class SelectionArgs : EventArgs
{public int Start;public int End;public SelectionArgs(int start, int end){Start = start;End = end;}
}

定义事件用于各平台本机代码的调用

public event EventHandler GetHtmlRequest;
public event EventHandler<string> SetHtmlRequest;
public event EventHandler<StyleArgs> StyleChangeRequested;
public event EventHandler<SelectionArgs> SelectionChangeHandler;

创建StyleChangeRequested的订阅事件以响应样式变更请求,对应不同的样式类型,调用不同的方法实现样式变更。


StyleChangeRequested =new EventHandler<StyleArgs>(
(sender, e) =>{var EditableText = platformView.EditableText;switch (e.Style){case StyleType.underline:UpdateUnderlineSpans(EditableText);break;case StyleType.italic:UpdateStyleSpans(TypefaceStyle.Italic, EditableText);break;case StyleType.bold:UpdateStyleSpans(TypefaceStyle.Bold, EditableText);break;case StyleType.backgoundColor:UpdateBackgroundColorSpans(EditableText, Microsoft.Maui.Graphics.Color.FromArgb(e.Params));break;case StyleType.foregroundColor:UpdateForegroundColorSpans(EditableText, Microsoft.Maui.Graphics.Color.FromArgb(e.Params));break;case StyleType.size:UpdateAbsoluteSizeSpanSpans(EditableText, int.Parse(e.Params));break;default:break;}});

实现复合样式

选择范围

android端使用SelectionStart和SelectionEnd获取选择范围,iOS端使用SelectedRange获取选择范围

//Androidint getSelectionStart() => platformView.SelectionStart;
int getSelectionEnd() => platformView.SelectionEnd;//iOS
NSRange getSelectionRange() => platformView.SelectedRange;

字号

MAUI控件中字号使用FontSize属性单位为逻辑像素,与DPI设置相关联。
在android本机平台中,字号通过为EditableText对象设置AbsoluteSizeSpan实现,代码如下


void UpdateAbsoluteSizeSpanSpans(IEditable EditableText, int size)
{var spanType = SpanTypes.InclusiveInclusive;EditableText.SetSpan(new AbsoluteSizeSpan(size, true), getSelectionStart(), getSelectionEnd(), spanType);SetEditableText(EditableText, platformView);
}

字体颜色与背景色

Android平台中,字体颜色与背景色通过为EditableText对象设置ForegroundColorSpan和BackgroundColorSpan实现

void UpdateForegroundColorSpans(IEditable EditableText, Microsoft.Maui.Graphics.Color color)
{var spanType = SpanTypes.InclusiveInclusive;EditableText.SetSpan(new ForegroundColorSpan(color.ToAndroid()), getSelectionStart(), getSelectionEnd(), spanType);SetEditableText(EditableText, platformView);
}void UpdateBackgroundColorSpans(IEditable EditableText, Microsoft.Maui.Graphics.Color color)
{var spanType = SpanTypes.InclusiveInclusive;EditableText.SetSpan(new BackgroundColorSpan(color.ToAndroid()), getSelectionStart(), getSelectionEnd(), spanType);SetEditableText(EditableText, platformView);
}

字体下划线

将选择文本选择范围内若包含下划线,则移除下划线,否则添加下划线

Android平台中通过为EditableText对象设置UnderlineSpan实现为文本添加下划线,通过RemoveSpan方法可以移除下划线,

但选择范围可能已包含下划线片段的一部分,因此移除此下划线片段后,需要重新添加下划线片段,以实现部分移除的效果


void UpdateUnderlineSpans(IEditable EditableText)
{var underlineSpans = EditableText.GetSpans(getSelectionStart(), getSelectionEnd(), Java.Lang.Class.FromType(typeof(UnderlineSpan)));bool hasFlag = false;var spanType = SpanTypes.InclusiveInclusive;foreach (var span in underlineSpans){hasFlag = true;var spanStart = EditableText.GetSpanStart(span);var spanEnd = EditableText.GetSpanEnd(span);var newStart = spanStart;var newEnd = spanEnd;var startsBefore = false;var endsAfter = false;if (spanStart < getSelectionStart()){newStart = getSelectionStart();startsBefore = true;}if (spanEnd > getSelectionEnd()){newEnd = getSelectionEnd();endsAfter = true;}EditableText.RemoveSpan(span);if (startsBefore){EditableText.SetSpan(new UnderlineSpan(), spanStart, newStart, SpanTypes.ExclusiveExclusive);}if (endsAfter){EditableText.SetSpan(new UnderlineSpan(), newEnd, spanEnd, SpanTypes.ExclusiveExclusive);}}if (!hasFlag){EditableText.SetSpan(new UnderlineSpan(), getSelectionStart(), getSelectionEnd(), spanType);}SetEditableText(EditableText, platformView);
}

字体加粗与斜体

Android平台中,字体粗细与斜体通过为EditableText对象设置StyleSpan实现,与设置字体下划线一样,需要处理选择范围内已包含StyleSpan的情况

TypefaceStyle提供了Normal、Bold、Italic、BoldItalic四种字体样式,粗体+斜体样式是通过组合实现的,因此需要处理样式叠加问题


void UpdateStyleSpans(TypefaceStyle flagStyle, IEditable EditableText)
{var styleSpans = EditableText.GetSpans(getSelectionStart(), getSelectionEnd(), Java.Lang.Class.FromType(typeof(StyleSpan)));bool hasFlag = false;var spanType = SpanTypes.InclusiveInclusive;foreach (StyleSpan span in styleSpans){var spanStart = EditableText.GetSpanStart(span);var spanEnd = EditableText.GetSpanEnd(span);var newStart = spanStart;var newEnd = spanEnd;var startsBefore = false;var endsAfter = false;if (spanStart < getSelectionStart()){newStart = getSelectionStart();startsBefore = true;}if (spanEnd > getSelectionEnd()){newEnd = getSelectionEnd();endsAfter = true;}if (span.Style == flagStyle){hasFlag = true;EditableText.RemoveSpan(span);EditableText.SetSpan(new StyleSpan(TypefaceStyle.Normal), newStart, newEnd, spanType);}else if (span.Style == TypefaceStyle.BoldItalic){hasFlag = true;EditableText.RemoveSpan(span);var flagLeft = TypefaceStyle.Bold;if (flagStyle == TypefaceStyle.Bold){flagLeft = TypefaceStyle.Italic;}EditableText.SetSpan(new StyleSpan(flagLeft), newStart, newEnd, spanType);}if (startsBefore){EditableText.SetSpan(new StyleSpan(span.Style), spanStart, newStart, SpanTypes.ExclusiveExclusive);}if (endsAfter){EditableText.SetSpan(new StyleSpan(span.Style), newEnd, spanEnd, SpanTypes.ExclusiveExclusive);}}if (!hasFlag){EditableText.SetSpan(new StyleSpan(flagStyle), getSelectionStart(), getSelectionEnd(), spanType);}SetEditableText(EditableText, platformView);
}

序列化和反序列化

所见即所得的内容需要被序列化和反序列化以便存储或传输,我们仍然使用HTML作为中间语言,好在Android和iOS平台都有HTML互转的对应实现。

  • Android平台中,Android.Text.Html提供了FromHtml()和Html.ToHtml(),
  • iOS中的NSAttributedStringDocumentAttributes提供了DocumentType属性,可以设置为NSHTMLTextDocumentType,使用它初始化AttributedString或调用AttributedString.GetDataFromRange()方法实现HTML和NSAttributedString的互转。

跨平台实现

在Platform/Android目录下创建HtmlParser.Android作为Android平台序列化和反序列化的实现。

public static class HtmlParser_Android
{public static ISpanned HtmlToSpanned(string htmlString){ISpanned spanned = Html.FromHtml(htmlString, FromHtmlOptions.ModeCompact);return spanned;}public static string SpannedToHtml(ISpanned spanned){string htmlString = Html.ToHtml(spanned, ToHtmlOptions.ParagraphLinesIndividual);return htmlString;}
}

在Platform/iOS目录下创建HtmlParser.iOS作为iOS平台序列化和反序列化的实现。

public static class HtmlParser_iOS
{static nfloat defaultSize = UIFont.SystemFontSize;static UIFont defaultFont;public static NSAttributedString HtmlToAttributedString(string htmlString){var nsString = new NSString(htmlString);var data = nsString.Encode(NSStringEncoding.UTF8);var dictionary = new NSAttributedStringDocumentAttributes();dictionary.DocumentType = NSDocumentType.HTML;NSError error = new NSError();var attrString = new NSAttributedString(data, dictionary, ref error);var mutString = ResetFontSize(new NSMutableAttributedString(attrString));return mutString;}static NSAttributedString ResetFontSize(NSMutableAttributedString attrString){defaultFont = UIFont.SystemFontOfSize(defaultSize);attrString.EnumerateAttribute(UIStringAttributeKey.Font, new NSRange(0, attrString.Length), NSAttributedStringEnumeration.None, (NSObject value, NSRange range, ref bool stop) =>{if (value != null){var oldFont = (UIFont)value;var oldDescriptor = oldFont.FontDescriptor;var newDescriptor = defaultFont.FontDescriptor;bool hasBoldFlag = false;bool hasItalicFlag = false;if (oldDescriptor.SymbolicTraits.HasFlag(UIFontDescriptorSymbolicTraits.Bold)){hasBoldFlag = true;}if (oldDescriptor.SymbolicTraits.HasFlag(UIFontDescriptorSymbolicTraits.Italic)){hasItalicFlag = true;}if (hasBoldFlag && hasItalicFlag){uint traitsInt = (uint)UIFontDescriptorSymbolicTraits.Bold + (uint)UIFontDescriptorSymbolicTraits.Italic;newDescriptor = newDescriptor.CreateWithTraits((UIFontDescriptorSymbolicTraits)traitsInt);}else if (hasBoldFlag){newDescriptor = newDescriptor.CreateWithTraits(UIFontDescriptorSymbolicTraits.Bold);}else if (hasItalicFlag){newDescriptor = newDescriptor.CreateWithTraits(UIFontDescriptorSymbolicTraits.Italic);}var newFont = UIFont.FromDescriptor(newDescriptor, defaultSize);attrString.RemoveAttribute(UIStringAttributeKey.Font, range);attrString.AddAttribute(UIStringAttributeKey.Font, newFont, range);}});return attrString;}public static string AttributedStringToHtml(NSAttributedString attributedString){var range = new NSRange(0, attributedString.Length);var dictionary = new NSAttributedStringDocumentAttributes();dictionary.DocumentType = NSDocumentType.HTML;NSError error = new NSError();var data = attributedString.GetDataFromRange(range, dictionary, ref error);var htmlString = new NSString(data, NSStringEncoding.UTF8);return htmlString;}
}

集成至编辑器

在所见即所得编辑器中设置两个方法,一个用于获取编辑器中的内容,一个用于设置编辑器中的内容。


public void SetHtmlText(string htmlString)
{HtmlString = htmlString;SetHtmlRequest(this, htmlString);
}public string GetHtmlText()
{GetHtmlRequest(this, new EventArgs());return HtmlString;
}

在HandlerChanged事件方法中的各平台代码段中添加如下代码:

GetHtmlRequest = new EventHandler((sender, e) =>{var editor = (WysiwygContentEditor)sender;HtmlString=HtmlParser_Android.SpannedToHtml(platformView.EditableText);});
SetHtmlRequest =new EventHandler<string>((sender, htmlString) =>{platformView.TextFormatted = HtmlParser_Android.HtmlToSpanned(htmlString);});

在富文本编辑器中的内容,最终会生成一个带有内联样式的HTML字符串,如下所示:

在这里插入图片描述

在这里插入图片描述

创建控件

控件由所见即所得编辑器和工具栏组成,所见即所得编辑器用于显示和编辑内容,工具栏用于设置字号、颜色、加粗、斜体、下划线

在这里插入图片描述

创建RichTextEditor的带有Xaml的ContentView。将所见即所得编辑器放置中央,工具栏放置在底部。

<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"xmlns:controls="clr-namespace:RichTextEditor.Controls;assembly=RichTextEditor"x:Class="RichTextEditor.Controls.RichTextEditor"><Border><Grid><Grid.RowDefinitions><RowDefinition Height="1*"></RowDefinition><RowDefinition Height="Auto"></RowDefinition><RowDefinition Height="Auto"></RowDefinition></Grid.RowDefinitions><controls:WysiwygContentEditor MinimumHeightRequest="150"AutoSize="TextChanges"BackgroundColor="{StaticResource PhoneContrastBackgroundBrush}"IsSpellCheckEnabled="false"x:Name="MainEditor"></controls:WysiwygContentEditor></Grid></Border>
</ContentView>

工具栏内的按钮横向排列

<HorizontalStackLayout Grid.Row="3"Spacing="5"Margin="0,10"><Button Text="{Binding Source={x:Reference TextSizeCollectionView}, Path=SelectedItem.Name, FallbackValue=Auto}"Style="{StaticResource RichTextButtonStyle}"Clicked="TextSizeButton_Clicked"x:Name="TextSizeButton"></Button><Button Text="Color"TextColor="{Binding Source={x:Reference ColorCollectionView}, Path=SelectedItem}"Style="{StaticResource RichTextButtonStyle}"Clicked="TextColorButton_Clicked"x:Name="TextColorButton"></Button><Button Text="B"Style="{StaticResource RichTextButtonStyle}"FontAttributes="Bold"x:Name="BoldButton"Clicked="BoldButton_Clicked"></Button><Button Text="I"Style="{StaticResource RichTextButtonStyle}"FontAttributes="Italic"x:Name="ItalicButton"Clicked="ItalicButton_Clicked"></Button><Button Text="U"Style="{StaticResource RichTextButtonStyle}"FontAttributes="None"x:Name="UnderLineButton"Clicked="UnderLineButton_Clicked"></Button>
</HorizontalStackLayout>

在这里插入图片描述

配置两个选择器:TextSizeCollectionView为字体大小选择器,ColorCollectionView为字体颜色选择器。

当点击字体大小选择器时,弹出字体大小选择器,当点击字体颜色选择器时,弹出字体颜色选择器。

在这里插入图片描述

在这里插入图片描述

<VerticalStackLayout x:Name="OptionsLayout"Grid.Row="2"Spacing="5"><CollectionView x:Name="TextSizeCollectionView"Background="Transparent"SelectionChanged="TextSizeCollectionView_SelectionChanged"SelectionMode="Single"HeightRequest="45"><CollectionView.ItemsLayout><LinearItemsLayout Orientation="Horizontal"ItemSpacing="5"></LinearItemsLayout></CollectionView.ItemsLayout><CollectionView.ItemTemplate><DataTemplate><Border x:Name="TargetElement"Style="{StaticResource SelectableLayoutStyle}"Background="{StaticResource PhoneContrastBackgroundBrush}"Padding="5,0"><Label Text="{Binding Name}"TextColor="{StaticResource PhoneForegroundBrush}"VerticalOptions="Center"FontSize="{Binding Value}"></Label></Border></DataTemplate></CollectionView.ItemTemplate></CollectionView><CollectionView x:Name="ColorCollectionView"SelectionChanged="ColorCollectionView_SelectionChanged"SelectionMode="Single"HeightRequest="45"><CollectionView.ItemsLayout><LinearItemsLayout Orientation="Horizontal"ItemSpacing="5"></LinearItemsLayout></CollectionView.ItemsLayout><CollectionView.ItemTemplate><DataTemplate><Border x:Name="TargetElement"Style="{StaticResource SelectableLayoutStyle}"BackgroundColor="{Binding}"WidthRequest="40"HeightRequest="40"StrokeShape="RoundRectangle 40"></Border></DataTemplate></CollectionView.ItemTemplate></CollectionView>
</VerticalStackLayout>

后端代码,绑定一些默认值


public static List<Color> DefaultTextColorList = new List<Color>() {Color.FromArgb("#000000"),Color.FromArgb("#F9371C"),Color.FromArgb("#F97C1C"),Color.FromArgb("#F9C81C"),Color.FromArgb("#41D0B6"),Color.FromArgb("#2CADF6"),Color.FromArgb("#6562FC")
};public static List<TextSize> DefaultTextSizeList = new List<TextSize>() {new TextSize(){Name="Large", Value=22},new TextSize(){Name="Middle", Value=18},new TextSize(){Name="Small", Value=12},
};

效果如下:

在这里插入图片描述

使用控件

在MainPage中使用RichTextEditor,代码如下


<controls:RichTextEditor  x:Name="MainRichTextEditor"Text="{Binding Content}"Placeholder="{Binding PlaceHolder}"></controls:RichTextEditor>

MainRichTextEditor.GetHtmlText()测试获取富文本编辑器Html序列化功能。

private async void Button_Clicked(object sender, EventArgs e)
{var html = this.MainRichTextEditor.GetHtmlText();await DisplayAlert("GetHtml()", html, "OK");
}

最终效果

在这里插入图片描述

已知问题

  • HTML样式会重复添加

项目地址

我在maui-sample项目中的一些控件,打算做成一个控件库,方便大家使用。控件库地址在下方。

maui-sample项目作为控件库孵化器,代码可能会有点乱,也没有经过严格的测试。当控件完善到一定程度,我会把控件封装起来放到控件库中。如果你有好的控件,欢迎pull request。

maui-sample:
Github:maui-samples

Mato.Maui控件库
Mato.Maui


http://www.ppmy.cn/news/333662.html

相关文章

bzoj2986

2986: Non-Squarefree Numbers Time Limit: 10 Sec Memory Limit: 128 MB Submit: 53 Solved: 30 [ Submit][ Status][ Discuss] Description 一个正整数K被称为squarefree,如果它没有一个D^2(D>1)这样的约数。 Input 读入一个正整数N Output 找出第N个不是squarefree的…

广数928te_广数928te2说明书

广 州 数 控 GSK928TE2 数控系统用户手册 GSK928TE/GSK928TC 车床数控系统 使 用 手 册 广 州 数 控 GSK928TE 数控系统用户手册 前 言 感谢您选用广州数控设备有限公司生产的 GSK928TE/GSK928TC 数控系统 , 本说明书提供了 使 用本系统所需知识及注意事项 . 操作不当可能引起意…

9282

//编写函数void fun(int array[3][3]),实现矩阵的转置&#xff08;行列互换&#xff09; #include<stdio.h> void fun(int a[3][3]) { int i,j; int b; for(i0;i<3;i) for(j0;j<3;j) if(i<j) { ba[i][j]; a[i][j]a[j][i]; a[j][i]b; } } void main() { int i,j…

D - 3978 Primes

Primes Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 4075 Accepted: 1579 Description A pretty straight forward task, calculate the number of primes between 2 integers. Given 2 integers A ≤ B < 105 what’s the number …

广数928te_广数928TE系统说明书

广 州 数 控 GSK928TE 数控系统用户手册 GSK928TE/GSK928TC 车床数控系统 使 用 手 册 广 州 数 控 GSK928TE 数控系统用户手册 前 言 感谢您选用广州数控设备有限公司生产的GSK928TE/GSK928TC数控系统,本说明书提供了使 用本系统所需知识及注意事项. 操作不当可能引起意外事故…

HDUOJ 2819 Swap

HDUOJ 2819 Swap 题目链接 Problem Description Given an N*N matrix with each entry equal to 0 or 1. You can swap any two rows or any two columns. Can you find a way to make all the diagonal entries equal to 1? Input There are several test cases in the …

广数980tc3从u盘复制到系统_广数980tc3数控车床

广数980tc3数控车床 日期:2020-06-16 00:00 来源:未知 浏览: 一:广数980tc3数控车床技术百科 1:广数980Tc3和980TDc有哪些不一样 答:看说明书不就明白了。 2:广数控980tc3系列如何实现wifi数据传输 答:几乎所有数控系统的程序都是ASCII码格式的,而TXT文件本身也是ASCI…

国标GH5188高温合金

固溶强化是指纯金属材料经过适度的细晶强化后&#xff0c;强度、强度提高 的状况。其原因归结为溶质原子和织造的配对t检查&#xff0c;该效果始于溶质引起的一部分点阵式畸变。固溶体分为混乱固溶体和井然有序固溶体&#xff0c;其加强原理不同。 GH5188合金原素固溶基材金属材…

HDU-1298-T9

HDU-1298-T9 http://acm.hdu.edu.cn/showproblem.php?pid1298 很好的一题&#xff0c;字典树DFS&#xff0c;思路参考swm8023大牛的 题意是模拟手机输入法&#xff0c;给出几个单词即频度&#xff0c;再给出几个数字串&#xff0c;确定对于给定的一个数字串&#xff0c;每输…

Javaweb学习路线(2)——Maven

一、概念 Maven 是 apache 旗下的一个开源项目&#xff0c;是一款用于管理和构建java项目的工具。 二、作用 依赖管理&#xff1a; 动态管理jar包&#xff0c;避免版本冲突。统一项目结构&#xff1a; 提供标准、统一的项目结构。项目构建&#xff1a; 标准跨平台的自动化项目…

智能工具Cursor安装和使用

一、Cursor介绍 Cursor.so是一个软件开发工具&#xff0c;是一个集成了 GPT的直接可以访问的&#xff0c;优秀而强大的智能AI代码生成工具&#xff0c;使用GPT-3.5免费。 它可以快速编写、编辑和聊天关于你的代码。它支持多种编程语言&#xff0c;如Python、Java、JavaScript等…

【零基础学JS - 11 】javaScript中的if..else表达式

&#x1f468;‍&#x1f4bb; 作者简介&#xff1a;程序员半夏 , 一名全栈程序员&#xff0c;擅长使用各种编程语言和框架&#xff0c;如JavaScript、React、Node.js、Java、Python、Django、MySQL等.专注于大前端与后端的硬核干货分享,同时是一个随缘更新的UP主. 你可以在各个…

CPU 技术名词

1、 CPU内核 epBpeqg CPU的中间就是我们平时称作核心芯片或CPU内核的地方&#xff0c;这颗由单晶硅做成的芯片可以说是电脑的大脑了&#xff0c;所有的计算、接受/存储命令、处理数据都是在这指甲盖大小的地方进行的。目前绝大多数CPU都采用了一种翻转内核的封装形式&#xf…

Linux——一

一、Linux Linux目录结构(掌握) FHS标准&#xff1a; /boot&#xff1a;启动目录&#xff0c;内核存放地/etc&#xff1a;配置文件存放地/tmp&#xff1a;程序产生的临时文件/home&#xff1a;用户的目录&#xff0c;新增用户账号时&#xff0c;用户的家目录都存放在此目录/l…

DJANGO查询ZABBIX6长时间的监控队列

一.登陆ZABBIX获取队列信息 先写一个类,实现: 1.登陆ZABBIX,获取KEY,再用这个KEY通过远程命令使用zabbix_get的方式拿到队列 2.拿到队列信息后比对ZABBIX后台数据库,获取监控项的信息,并根据队列的nextcheck信息进筛选和数据重组,此时将监控队列的监控项,PROXY,AGENT,nextch…

几种技巧让大模型(ChatGPT、文心一言)帮你提高写代码效率!

代码神器 自从大模型推出来之后&#xff0c;似乎没有什么工作是大模型不能做的。特别是在文本生成、文案写作、代码提示、代码生成、代码改错等方面都表现出不错的能力。下面我将介绍运用大模型写代码的几种方式&#xff0c;帮助程序员写出更好的代码&#xff01;&#xff08;…

Linux系统:CentOS编译Linux内核

目录 一、实验 1.下载内核 2.解压内核源码 3.配置依赖的环境 4.进入源码目录&#xff0c;使用make menuconfig开启菜单选项&#xff0c;手动选择内核功能 5.编译内核 6.安装模块 7.安装内核 8.验证新内核版本 一、实验 1.下载内核 &#xff08;1&#xff09;官网下载…

kotlin 解决构造函数兼容性问题

data class Person(private val head: String,val hand: String ) {} val p Person("head", "hand")Log.d("Alex", "Person $p") 打印结果&#xff1a; 2023-06-11 22:30:54.764 21840-21840 Alex com.example…

智能diy官网小程序至尊版v1.0.73+微信前端

&#x1f388; 限时活动领体验会员&#xff1a;可下载程序网创项目短视频素材 &#x1f388; &#x1f389; 有需要的朋友记得关赞评&#xff0c;文章底部来交流&#xff01;&#xff01;&#xff01; &#x1f389; ✨ 源码介绍 1、h5万*能页增加跳转小程序组件 2、功能链接弹…

【VSCode】Unexpected GDB output from command “-exec-run“(error 1450)

问题排查 1. 检查MinGW是否安装成功 在命令行窗口输入 g verion2. 若是没有安装成功&#xff0c;则配置路径 在path路径下添加MinGW安装的目录下的bin文件 例如&#xff1a;D:\MinGW\i686\bin3.若问题仍然存在&#xff0c;并且出现被电脑拦截的情况 原因&#xff1a;程序出…
最新文章