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

【WPF】自定义控件:ShellEditControl-同列单元格编辑支持文本框、下拉框和弹窗

需要实现表格同一列,单元格可以使用文本框直接输入编辑、下拉框选择和弹窗,文本框只能输入数字,弹窗中的数据是若干位的二进制值。

本文提供了两种实现单元格编辑状态下,不同编辑控件的方法:
1、DataTrigger控制控件的显示;
2、定义DataTemplateSelector选择器根据数据返回不同模板。

效果如下:
![[gif-ShellEditControl.gif]]

数据

行数据类定义

每行数据需要定义属性:

  • detail:string,描述
  • valueType:enum,值类型
  • setValue:object,设定值,需要定义成可更新属性(mvvm)
  • valueOptions:List<optionModel>,值类型为选项时,此属性有值
  • selectedOptionItem:optionModel,所选的元素,需要定义成可更新属性(mvvm)
  • childValues:ObservableCollection<ChildValueModel>,值类型为对象时,此属性有值
  • EditChildValueCommand:RelayCommand,编辑childValues发生弹窗事件按钮
  • editType:string/enum,修改类型,值为不可修改时单元格不可编辑
    定义方法
  • ParseValueToChildValue:setValue转childValues
public class GirdData : ObservableObject
{public string detail { get; set; }public ValueTypeEnum valueType { get; set; }private object _value;public object setValue{get{return _value;}set{//弹窗数据,二进制 《---》 十进制if (valueType == ValueTypeEnum.Object) childValues = ParseValueToChildValue(value, defaltChildValues);//文本框数据,string <----> 数值//value未填写时默认为“--”if (valueType == ValueTypeEnum.Number && value.ToString() != "--")try { //decimalPlaces小数点位数,类中应当有该属性,这里省略value = Decimal.Round(Decimal.Parse(value.ToString()), decimalPlaces); } catch { }OnPropertyChanged(ref _value, value);}}public List<OptionModel> valueOptions { get; set; }public OptionModel selectedOptionItem{get{if (this.valueType != ValueTypeEnum.Option) return null;//获取setValue对应的选项if (setValue.ToString() == "--") return new OptionModel();return valueOptions.Find(_ => _.optionValue.ToString() == setValue.ToString());}set{if (this.valueType != ValueTypeEnum.Option) return;//获取选中选项的值this.setValue = value.optionValue;}}public ObservableCollection<ChildValueModel> childValues { get; set; }public RelayCommand EditChildValueCommand { get; set; }//十进制转二进制public ObservableCollection<ChildValueModel> ParseValueToChildValue(object oValue, ObservableCollection<ChildValueModel> childValues){return ParseValueToChildValue_static(oValue, childValues);}public static ObservableCollection<ChildValueModel> ParseValueToChildValue_static(object oValue, ObservableCollection<ChildValueModel> childValues){int value = int.Parse(oValue.ToString());string sValues = Convert.ToString(value, 2);if (sValues.Length > childValues.Count) return null;sValues = sValues.PadLeft(childValues.Count, '0');for (int i = 0; i < childValues.Count; i++){childValues[childValues.Count - 1 - i].value = int.Parse(sValues[i].ToString());}return childValues;}
}
public enum ValueTypeEnum
{Number,Option,Object
}
//下拉框选项的类
public class OptionModel
{public int optionValue { get; set; }public string detail { get; set; }public override string ToString(){return fullDetail;}//页面中展示的选项及结果的字符串格式 值[描述]public string fullDetail{get{string res = optionValue + "[" + detail + "]";return detail == null ? "--" : res;}}
}
//弹窗中各位二进制对应类
public class ChildValueModel : ObservableObject, ICloneable
{public Action InvokeCollectionChangedAction;private object _value;public object value{get => _value;set{OnPropertyChanged(ref _value, value);//其中一位发生改变,对应的十进制发生变化,触发该事件InvokeCollectionChangedAction?.Invoke();}}public string propertyName { get; set; }public object Clone(){return new ChildValueModel{value = this.value,propertyName = this.propertyName};}
}

生成表格数据

写一些假数据,格式如下

new ObservableCollection<GirdDataModel>{new GirdData(){detail:**,valueType:ValueTypeEnum.**,setValue:**,//如“--”、1、23.432editType:**,//valueType==ValueTypeEnum.Option//如valueOptions = new List<OptionModel>{new OptionModel{ optionValue=0,detail="正向"},new OptionModel{ optionValue=1,detail="反向"}},//valueType==ValueTypeEnum.Object//如childValues = new ObservableCollection<ChildValueModel>{new ChildValueModel{ propertyName="bit0",value=0},new ChildValueModel{ propertyName="bit1",value=0},new ChildValueModel{ propertyName="bit2",value=0},new ChildValueModel{ propertyName="bit3",value=0},}},...
}

页面

表格页面

View

主要列包括

  • 描述 - detail
  • 设定值 - setValue
    <DataGridTemplateColumn.CellTemplate>自定义单元格未编辑时内容模板
  • 值类型为Option时,绑定selectedOptionItem,会自动调用ToString,显示格式:值[描述];
  • 值类型为其他时,绑定setValue;
    <DataGridTemplateColumn.CellEditingTemplate>自定义单元格编辑时内容模板
    提供两种实现不同值类型,单元格编辑方式不同的方法
1、DataTrigger控制控件的显示
  • 值类型为Number时,显示文本框,绑定setValue;
  • 值类型为Option时,显示下拉框,ItemsSource绑定valueOptions,SelectedItem绑定selectedOptionItem,下拉框元素模板本文绑定fullDetail,格式:值[描述];
  • 值类型为Object时,显示文本+详情按钮,文本绑定setValue,按钮绑定EditChildValueCommand(详细方法定义在VM中),并传值行全部数据。
<DataGrid ItemsSource="{Binding GridData,Mode=TwoWay}" RowBackground="#E4FAF5"AlternatingRowBackground="#C8F0F0"CanUserAddRows="False"AutoGenerateColumns="False"><DataGrid.Columns><DataGridTextColumn Header="描述" Binding="{Binding detail,Mode=OneWay}" IsReadOnly="True"/><DataGridTemplateColumn Header="设定值"><DataGridTemplateColumn.CellTemplate><DataTemplate><Grid><TextBlock><TextBlock.Style><Style TargetType="TextBlock"><Setter Property="Text" Value="{Binding setValue,StringFormat=N0,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/><Style.Triggers><DataTrigger Binding="{Binding valueType}" Value="Option"><Setter Property="Text" Value="{Binding selectedOptionItem}"/></DataTrigger><DataTrigger Binding="{Binding decimalPlaces}" Value="3"><Setter Property="Text" Value="{Binding setValue,StringFormat=N3,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/></DataTrigger></Style.Triggers></Style></TextBlock.Style></TextBlock></Grid></DataTemplate></DataGridTemplateColumn.CellTemplate><DataGridTemplateColumn.CellEditingTemplate><DataTemplate><Grid><Grid.Resources><Style TargetType="TextBox" x:Key="SetValueBox"><Setter Property="Text" Value="{Binding setValue,StringFormat=N0,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/><Setter Property="Visibility" Value="Collapsed"/><Setter Property="Template"><Setter.Value><ControlTemplate><Grid><Rectangle StrokeThickness="1"/><TextBox Margin="1"Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Text,Mode=TwoWay}"BorderThickness="0"Background="Transparent"VerticalAlignment="Center"Foreground="WhiteSmoke"/></Grid></ControlTemplate></Setter.Value></Setter><Style.Triggers><DataTrigger Binding="{Binding valueType}" Value="Number"><Setter Property="Visibility" Value="Visible"/></DataTrigger><DataTrigger Binding="{Binding decimalPlaces}" Value="3"><Setter Property="Text" Value="{Binding setValue,StringFormat=N3,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/></DataTrigger></Style.Triggers></Style></Grid.Resources><TextBox Style="{StaticResource SetValueBox}"/><ComboBox ItemsSource="{Binding valueOptions}"SelectedItem="{Binding selectedOptionItem}"><ComboBox.Style><Style TargetType="ComboBox"><Setter Property="Visibility" Value="Collapsed"/><Style.Triggers><DataTrigger Binding="{Binding valueType}" Value="Option"><Setter Property="Visibility" Value="Visible"/></DataTrigger></Style.Triggers></Style></ComboBox.Style><ComboBox.ItemTemplate><DataTemplate><TextBlock Text="{Binding fullDetail}"/></DataTemplate></ComboBox.ItemTemplate></ComboBox><Grid><Grid.Style><Style TargetType="Grid"><Setter Property="Visibility" Value="Collapsed"/><Style.Triggers><DataTrigger Binding="{Binding valueType}" Value="Object"><Setter Property="Visibility" Value="Visible"/></DataTrigger></Style.Triggers></Style></Grid.Style><TextBlock Text="{Binding setValue,Mode=TwoWay}"/><Button Width="20" Content="..." HorizontalAlignment="Right"Command="{Binding EditChildValueCommand}"CommandParameter="{Binding}"/></Grid></Grid></DataTemplate></DataGridTemplateColumn.CellEditingTemplate></DataGridTemplateColumn></DataGrid.Columns>
</DataGrid>
2、定义DataTemplateSelector选择器

选择器可以根据值类型和修改类型,返回不同单元格编辑模板
选择器逻辑如下:

public class CellEditTemplateSelector : DataTemplateSelector
{public DataTemplate TextBoxTemplate { get; set; }public DataTemplate ComboxTemplate { get; set; }public DataTemplate PopupButtonTemplate { get; set; }public DataTemplate UnEnableTemplate { get; set; }public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container) {if (item is GirdDataModel) {GirdDataModel data = item as GirdDataModel;if (data.editType == "不可修改") return UnEnableTemplate;switch (data.valueType){case ValueTypeEnum.Number:return TextBoxTemplate;case ValueTypeEnum.Option:return ComboxTemplate;case ValueTypeEnum.Object:return PopupButtonTemplate;}}return base.SelectTemplate(item, container);}
}

xaml中定义不同的单元格编辑模板,然后将选择器应用值CellEditingTemplateSelector属性。

<UserControl.Resources><local:SetValueTextConverter x:Key="SetValueTextConverter"/><local:SetValueTextEditingConverter x:Key="SetValueTextEditingConverter"/><local:CellEditTemplateSelector x:Key="CellEditTemplateSelector"><local:CellEditTemplateSelector.TextBoxTemplate><DataTemplate><TextBox><TextBox.Text><MultiBinding Converter="{StaticResource SetValueTextEditingConverter}"><Binding Path="setValue" UpdateSourceTrigger="PropertyChanged" /><Binding Path="decimalPlaces"/></MultiBinding></TextBox.Text></TextBox></DataTemplate></local:CellEditTemplateSelector.TextBoxTemplate><local:CellEditTemplateSelector.ComboxTemplate><DataTemplate><ComboBox ItemsSource="{Binding valueOptions}"SelectedItem="{Binding selectedOptionItem}"><ComboBox.ItemTemplate><DataTemplate><TextBlock Text="{Binding fullDetail}"/></DataTemplate></ComboBox.ItemTemplate></ComboBox></DataTemplate></local:CellEditTemplateSelector.ComboxTemplate><local:CellEditTemplateSelector.PopupButtonTemplate><DataTemplate><Grid><TextBlock Text="{Binding setValue,Mode=TwoWay}"/><Button Width="20" Content="..." HorizontalAlignment="Right"Command="{Binding EditChildValueCommand}"CommandParameter="{Binding}"/></Grid></DataTemplate></local:CellEditTemplateSelector.PopupButtonTemplate><local:CellEditTemplateSelector.UnEnableTemplate><DataTemplate><TextBlock Text="--"/></DataTemplate></local:CellEditTemplateSelector.UnEnableTemplate></local:CellEditTemplateSelector>
</UserControl.Resources>
...
<DataGrid ItemsSource="{Binding GridData,Mode=TwoWay}" RowBackground="#E4FAF5"AlternatingRowBackground="#C8F0F0"CanUserAddRows="False"AutoGenerateColumns="False"><DataGrid.Columns><DataGridTextColumn Header="描述" Binding="{Binding detail,Mode=OneWay}" IsReadOnly="True"/><DataGridTemplateColumn Header="设定值" CellEditingTemplateSelector="{StaticResource CellEditTemplateSelector}"><DataGridTemplateColumn.CellTemplate><DataTemplate><Grid><TextBlock><TextBlock.Style><Style TargetType="TextBlock"><Setter Property="Text" Value="{Binding setValue,StringFormat=N0,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/><Style.Triggers><DataTrigger Binding="{Binding valueType}" Value="Option"><Setter Property="Text" Value="{Binding selectedOptionItem}"/></DataTrigger><DataTrigger Binding="{Binding decimalPlaces}" Value="3"><Setter Property="Text" Value="{Binding setValue,StringFormat=N3,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/></DataTrigger></Style.Triggers></Style></TextBlock.Style></TextBlock></Grid></DataTemplate></DataGridTemplateColumn.CellTemplate></DataGridTemplateColumn></DataGrid.Columns>
</DataGrid>

ViewModel

private DataAccessForGrid dataAccessForGrid;
public ObservableCollection<GirdData> gridData { get; set; }
public ShellEditControl()
{dataAccessForGrid = new DataAccessForGrid();gridData = dataAccessForGrid.GetDataList();foreach (var _ in gridData){if (_.valueType == ValueTypeEnum.Object){//定义弹窗事件_.EditChildValueCommand = new RelayCommand((o) =>{ChildValueEditPopupOpen(_);});}}
}
//使用IOC模式打开弹窗
private void ChildValueEditPopupOpen(GirdData data)
{IChildValueEditPopupService service = IoC.Provide<IChildValueEditPopupService>();ChildValueEditPopupResult res = service.ChildValueEditPopupOpen(data);if (res.IsSuccess){data.setValue = res.setValue;}
}

弹窗页面

View

主要内容:表格(ChildValues)和当前值(SetValue)

<Window x:Class="bueatifulApp.Components.DataGridWithEdit.View.ChildValuePopup"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:bueatifulApp.Components.DataGridWithEdit.View"mc:Ignorable="d"Title="写入参数" Height="313" Width="400"Background="#DADFEA" ><Grid Margin="10"><Grid.RowDefinitions><RowDefinition Height="55"/><RowDefinition/><RowDefinition Height="30"/></Grid.RowDefinitions><Grid ><Grid.ColumnDefinitions><ColumnDefinition Width="100"/><ColumnDefinition/></Grid.ColumnDefinitions><Grid.RowDefinitions><RowDefinition Height="25"/></Grid.RowDefinitions><TextBlock VerticalAlignment="Center" Text="描述" Grid.Column="0" Grid.Row="1"/><TextBox Height="18" Text="{Binding Code}" IsEnabled="False" Grid.Column="1" Grid.Row="1"/></Grid><Grid Grid.Row="1"><DataGrid ItemsSource="{Binding ChildValues,Mode=TwoWay}" CanUserAddRows="False"AutoGenerateColumns="False"><DataGrid.Columns><DataGridTextColumn Header="属性名" Binding="{Binding propertyName,Mode=OneWay}" IsReadOnly="True"/><DataGridTextColumn Header="设定值" Binding="{Binding value,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/></DataGrid.Columns></DataGrid></Grid><Grid Grid.Row="2"><Grid.ColumnDefinitions><ColumnDefinition Width="200"/><ColumnDefinition/></Grid.ColumnDefinitions><Grid><Grid.ColumnDefinitions><ColumnDefinition Width="70"/><ColumnDefinition/></Grid.ColumnDefinitions><TextBlock VerticalAlignment="Center" Text="当前值"/><TextBox Height="18" Text="{Binding SetValue,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Grid.Column="1"/></Grid><Grid Grid.Column="1" HorizontalAlignment="Right"><Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition/></Grid.ColumnDefinitions><Button Command="{Binding OKCommand}" Height="25" Width="60" Content="确定" Margin="0,0,10,0"/><Button Command="{Binding CancelCommand}" Height="25" Width="60" Content="取消" Grid.Column="1"/></Grid></Grid></Grid>
</Window>

ViewModel

public class ChildValueEditViewModel : ObservableObject
{private string code;//描述private ObservableCollection<ChildValueModel> childValues;//表格数据private object setValue;//设定值public string Code{get => this.code;set => OnPropertyChanged(ref code, value);}public ObservableCollection<ChildValueModel> ChildValues{get => this.childValues;set => OnPropertyChanged(ref childValues, value);}public object SetValue{get => this.setValue;set => OnPropertyChanged(ref setValue, value);}
}public class ChildValueEditPopupViewModel : ChildValueEditViewModel
{public ICommand OKCommand { get; }public ICommand CancelCommand { get; }public IView View { get; }public ChildValueEditPopupViewModel(IView view){this.View = view;this.OKCommand = new RelayCommand((o) => this.OkAction());this.CancelCommand = new RelayCommand((o) => this.CancelAction());}public void OkAction(){this.View.CloseDialog(true); // close it with a successful result}public void CancelAction(){this.View.CloseDialog(false); // close it with a failed result}
}

服务

定义窗口打开事件
定义窗口打开时接受的数据

服务接口
public interface IChildValueEditPopupService
{Task<ChildValueEditPopupResult> ChildValueEditPopupOpenAsync(GirdData data);ChildValueEditPopupResult ChildValueEditPopupOpen(GirdData data);
}
public class ChildValueEditPopupResult : ObservableObject
{public bool IsSuccess { get; set; }private object _setValue;public string code { get; set; }public object setValue { get=>_setValue; set=>OnPropertyChanged(ref _setValue,value); }
}
服务实现
internal class ChildValueEditPopupService : IChildValueEditPopupService
{public ChildValueEditPopupResult ChildValueEditPopupOpen(GirdData data){var popup = new ChildValuePopup();popup.ViewModel.Code = data.detail;//需要深拷贝,才能正确修改大表数据popup.ViewModel.ChildValues = Copy.DeepCopy( data.childValues);foreach (var item in popup.ViewModel.ChildValues){//定义大表设定值响应事件item.InvokeCollectionChangedAction = () => {popup.ViewModel.SetValue = GirdDataModel.ParseChildValues_static(popup.ViewModel.ChildValues);};}popup.ViewModel.SetValue = data.setValue;bool result = popup.ShowDialog() == true;if (!result) {return new ChildValueEditPopupResult() { IsSuccess = false};}return new ChildValueEditPopupResult(){IsSuccess = true,code = popup.ViewModel.Code,setValue = popup.ViewModel.SetValue,}; }public async Task<ChildValueEditPopupResult> ChildValueEditPopupOpenAsync(GirdData data) {return await Application.Current.Dispatcher.InvokeAsync(() => {return ChildValueEditPopupOpen(data);});}
}
服务注册
 public partial class MainWindow : Window{public MainWindow(){InitializeComponent();IoC.Register<IChildValueEditPopupService>(new ChildValueEditPopupService());}}

相关文章:

【WPF】自定义控件:ShellEditControl-同列单元格编辑支持文本框、下拉框和弹窗

需要实现表格同一列&#xff0c;单元格可以使用文本框直接输入编辑、下拉框选择和弹窗&#xff0c;文本框只能输入数字&#xff0c;弹窗中的数据是若干位的二进制值。 本文提供了两种实现单元格编辑状态下&#xff0c;不同编辑控件的方法&#xff1a; 1、DataTrigger控制控件的…...

21天Python计划:零障碍学语法(更新完毕)

目录 序号标题链接day1Python下载和开发工具介绍https://blog.csdn.net/XiaoRungen/article/details/146583769?spm1001.2014.3001.5501day2数据类型、字符编码、文件处理https://blog.csdn.net/XiaoRungen/article/details/146603325?spm1011.2415.3001.5331day3基础语法与…...

深入剖析C++单例模式的八种实现演进与工程实践

深入剖析C单例模式的八种实现演进与工程实践 一、从基础到工业级&#xff1a;单例模式的演进图谱 1.1 基础实现的致命缺陷分析 // 初级版&#xff08;非线程安全&#xff09; class NaiveSingleton { public:static NaiveSingleton* getInstance() {if (!instance) {instanc…...

Seq2Seq - GRU补充讲解

nn.GRU 是 PyTorch 中实现门控循环单元&#xff08;Gated Recurrent Unit, GRU&#xff09;的模块。GRU 是一种循环神经网络&#xff08;RNN&#xff09;的变体&#xff0c;用于处理序列数据&#xff0c;能够更好地捕捉长距离依赖关系。 ⭐重点掌握输入输出部分输入张量&#…...

从零开始学Python游戏编程19-游戏循环模式1

在《从零开始学Python游戏编程18-函数3》中提到&#xff0c;可以对游戏代码进行重构&#xff0c;把某些代码写入函数中&#xff0c;主程序再调用这些函数&#xff0c;这样使得代码程序更容易理解和维护。游戏循环模式实际上也是把代码写入到若干个函数中&#xff0c;通过循环的…...

KWDB创作者计划—KWDB认知跃迁:多模架构与AI原生的数据库范式革命

引言&#xff1a;从存储到认知的范式迁移 在数字化转型进入深水区的2025年&#xff0c;全球每日新增数据量已突破3.5ZB&#xff0c;传统数据库的"存储-计算"二分法正面临根本性挑战。当AlphaFold4实现蛋白质全序列预测&#xff0c;工业数字孪生需处理百万级设备实时数…...

Java获取终端设备信息工具类

在很多场景中需要获取到终端设备的一些硬件信息等&#xff0c;获取的字段如下&#xff1a; 返回参数 参数含义备注systemName系统名称remoteIp公网iplocalIp本地ip取IPV4macmac地址去掉地址中的"-“或”:"进行记录cpuSerialcpu序列号hardSerial硬盘序列号drive盘符…...

【Linux网络与网络编程】08.传输层协议 UDP

传输层协议负责将数据从发送端传输到接收端。 一、再谈端口号 端口号标识了一个主机上进行通信的不同的应用程序。在 TCP/IP 协议中&#xff0c;用 "源IP"&#xff0c;"源端口号"&#xff0c;"目的 IP"&#xff0c;"目的端口号"&…...

没音响没耳机,把台式电脑声音播放到手机上

第一步&#xff0c;电脑端下载安装e2eSoft VSC虚拟声卡&#xff08;安装完成后关闭&#xff0c;不要点击和设置&#xff09; 第二步&#xff0c;电脑端下载安装&#xff08;SoundWire Server&#xff09;&#xff08;安装完成后不要关闭&#xff0c;保持默认配置&#xff09; 第…...

Dubbo(53)如何在Spring Boot中集成Dubbo?

在Spring Boot中集成Dubbo可以通过Spring Boot Starter来简化配置&#xff0c;以下是详细的步骤和相关代码示例。 1. 引入依赖 首先&#xff0c;在Spring Boot项目的 pom.xml 中添加Dubbo相关的依赖&#xff1a; <dependencies><!-- Spring Boot Starter --><…...

go学习记录(第一天)

%v&#xff0c;和%q是什么意思 %v —— 默认格式&#xff08;"value" 的缩写&#xff09; 作用&#xff1a;按值的默认格式输出&#xff0c;适用于任何类型。 代码示例&#xff1a; fmt.Printf("%v\n", "Hello") // 输出: Hello fmt.Printf…...

XDocument和XmlDocument的区别及用法

因为这几天用到了不熟悉的xml统计数据&#xff0c;啃了网上的资料解决了问题&#xff0c;故总结下xml知识。 1.什么是XML?2.XDocument和XmlDocument的区别3.XDocument示例1示例2&#xff1a;示例3&#xff1a; 4.XmlDocument5.LINQ to XML6.XML序列化(Serialize)与反序列化(De…...

error: failed to run custom build command for `yeslogic-fontconfig-sys v6.0.0`

rust使用plotters时遇到编译错误。 一、错误 error: failed to run custom build command for yeslogic-fontconfig-sys v6.0.0 二、解决方法 我用的是opensuse&#xff0c;使用下面命令可以解决问题。 sudo zypper in fontconfig-devel...

Blender安装基础使用教程

本博客记录安装Blender和基础使用&#xff0c;可以按如下操作来绘制标靶场景、道路标识牌等。 目录 1.安装Blender 2.创建面板资源 步骤 1: 设置 Blender 场景 步骤 2: 创建一个平面 步骤 3: 将 PDF 转换为图像 步骤 4-方法1: 添加材质并贴图 步骤4-方法2&#xff1a;创…...

GPT-4、Grok 3与Gemini 2.0 Pro:三大AI模型的语气、风格与能力深度对比

更新后的完整CSDN博客文章 以下是基于您的要求&#xff0c;包含修正后的幻觉率部分并保留原始信息的完整CSDN博客风格文章。幻觉率已调整为更符合逻辑的描述&#xff0c;其他部分保持不变。 GPT-4、Grok 3与Gemini 2.0 Pro&#xff1a;三大AI模型的语气、风格与能力深度对比 …...

【Git】从零开始使用git --- git 的基本使用

哪怕是野火焚烧&#xff0c;哪怕是冰霜覆盖&#xff0c; 依然是志向不改&#xff0c;依然是信念不衰。 --- 《悟空传》--- 从零开始使用git 了解 Gitgit创建本地仓库初步理解git结构版本回退 了解 Git 开发场景中&#xff0c;文档可能会经历若干版本的迭代。假如我们不进行…...

spring mvc 中 RestTemplate 全面详解及示例

RestTemplate 全面详解及示例 1. RestTemplate 简介 定义&#xff1a;Spring 提供的同步 HTTP 客户端&#xff0c;支持多种 HTTP 方法&#xff08;GET/POST/PUT/DELETE 等&#xff09;&#xff0c;用于调用 RESTful API。核心特性&#xff1a; 支持请求头、请求体、URI 参数的…...

智能指针之设计模式1

本文探讨一下智能指针和GOF设计模式的关系&#xff0c;如果按照设计模式的背后思想来分析&#xff0c;可以发现围绕智能指针的设计和实现有设计模式的一些思想体现。当然&#xff0c;它们也不是严格意义上面向对象的设计模式&#xff0c;毕竟它们没有那么分明的类层次体系&…...

Android 中支持旧版 API 的方法(API 30)

Android 中最新依赖库的版本支持 API 31 及以上版本&#xff0c;若要支持 API30&#xff0c;则对应的依赖库的版本就需要使用旧版本。 可通过修改模块级 build.gradle 文件来进行适配。 1、android 标签的 targetSdk 和 compileSdk 版本号 根据实际目标设备的 android 版本来…...

[特殊字符] Hyperlane:Rust 高性能 HTTP 服务器库,开启 Web 服务新纪元!

&#x1f680; Hyperlane&#xff1a;Rust 高性能 HTTP 服务器库&#xff0c;开启 Web 服务新纪元&#xff01; &#x1f31f; 什么是 Hyperlane&#xff1f; Hyperlane 是一个基于 Rust 语言开发的轻量级、高性能 HTTP 服务器库&#xff0c;专为简化网络服务开发而设计。它支…...

【深拷贝、浅拷贝】golang函数参数传递,变量复制后,操作变量参数,是否影响原有数据?全面解析

Golang中深拷贝与浅拷贝的详细解析&#xff0c;以及变量复制、函数参数传递等场景下对新旧变量影响的总结&#xff1a; 一拷贝与浅拷贝的核心区别 1. 浅拷贝&#xff08;Shallow Copy&#xff09; • 定义&#xff1a;仅复制数据的顶层结构&#xff0c;对引用类型字段&#x…...

RIP V2路由协议配置实验CISCO

1.RIP V2简介&#xff1a; RIP V2&#xff08;Routing Information Protocol Version 2&#xff09;是 RIP 路由协议的第二版&#xff0c;属于距离矢量路由协议&#xff0c;主要用于中小型网络环境。相较于 RIP V1&#xff0c;RIP V2 在功能和性能上进行了多项改进&#xff0c…...

《LNMP架构+Nextcloud私有云超维部署:量子级安全与跨域穿透实战》

项目实战-使用LNMP搭建私有云存储 准备工作 恢复快照&#xff0c;关闭安全软件 [rootserver ~]# setenforce 0[rootserver ~]# systemctl stop firewalld搭建LNMP环境 [rootserver ~]# yum install nginx mariadb-server php* -y# 并开启nginx服务并设置开机自启 [r…...

STM32 HAL库 OLED驱动实现

一、概述 1.1 OLED 显示屏简介 OLED&#xff08;Organic Light - Emitting Diode&#xff09;即有机发光二极管&#xff0c;与传统的 LCD 显示屏相比&#xff0c;OLED 具有自发光、视角广、响应速度快、对比度高、功耗低等优点。在嵌入式系统中&#xff0c;OLED 显示屏常被用…...

Excel通过VBA脚本去除重复数据行并保存

一、方法1:使用字典动态去重并保存 适用场景&#xff1a;需要灵活控制去重逻辑&#xff08;如保留最后一次出现的重复项&#xff09;时 Sub 动态去重保存到新表()Dim srcSheet As Worksheet, destSheet As WorksheetDim dict As Object, lastRow As Long, i As LongDim key A…...

大模型Prompt提示词越狱相关知识

大模型Prompt提示词越狱相关知识 一、什么是Prompt提示词越狱&#xff1f; 什么是Prompt提示词 ​ Prompt是指你向AI输入的内容&#xff0c;它直接指示AI该做什么任务或生成什么样的输出&#xff0c;简而言之&#xff0c; Prompt就是你与AI之间的“对话内容”&#xff0c;可…...

3DMAX笔记-UV知识点和烘焙步骤

1. 在展UV时&#xff0c;如何点击模型&#xff0c;就能选中所有这个模型的uv 2. 分多张UV时&#xff0c;不同的UV的可以设置为不同的颜色&#xff0c;然后可以通过颜色进行筛选。 3. 烘焙步骤 摆放完UV后&#xff0c;要另存为一份文件&#xff0c;留作备份 将模型部件全部分成…...

【新人系列】Golang 入门(十三):结构体 - 下

✍ 个人博客&#xff1a;https://blog.csdn.net/Newin2020?typeblog &#x1f4dd; 专栏地址&#xff1a;https://blog.csdn.net/newin2020/category_12898955.html &#x1f4e3; 专栏定位&#xff1a;为 0 基础刚入门 Golang 的小伙伴提供详细的讲解&#xff0c;也欢迎大佬们…...

Spring Boot 自定义商标(Logo)的完整示例及配置说明( banner.txt 文件和配置文件属性信息)

Spring Boot 自定义商标&#xff08;Logo&#xff09;的完整示例及配置说明 1. Spring Boot 商标&#xff08;Banner&#xff09;功能概述 Spring Boot 在启动时会显示一个 ASCII 艺术的商标 LOGO&#xff08;默认为 Spring 的标志&#xff09;。开发者可通过以下方式自定义&a…...

Ubuntu虚拟机Linux系统入门

目录 一、安装 Ubuntu Linux 20.04系统 1.1 安装前准备工作 1.1.1 镜像下载 1.1.2 创建新的虚拟机 二、编译内核源码 2.1 下载源码 2.2 指定编译工具 2.3 将根文件系统放到源码根目录 2.4 配置生成.config 2.5 编译 三、安装aarch64交叉编译工具 四、安装QEMU 五、…...