【WPF】根据选项值显示不同的编辑控件(使用DataTemplateSelector)

news/2024/7/3 6:37:54/文章来源:https://www.cnblogs.com/tcjiaan/p/18274217

接了一个小杂毛项目,大概情形是这样的:ZWT先生开的店是卖拆片机的,Z先生不仅卖机器,还贴心地提供一项服务:可以根据顾客需要修改两个电机的转向和转速(机器厂家有给SDK的,但Z自己不会写程序)。厂家有配套一个调节器,调整参数时连接到拆片机的串口上,然后旋转按钮可以调速,拨码开关可以设定电机正转还是反转。但Z觉得调速器长得像个马桶水箱似的,既不好看也不便携带。最惨的是,有的客户的车间里有很多台机子,一台一台的连上串口调很费劲。于是,学过电工的Z不知道哪搞了一个串口 Hub,电脑向 Hub 发数据,然后会将数据群发给所有连接的拆片机(这种Hub忘了叫什么,十几年前老周曾在某工厂里见过)。

Z先生经过 N 个中间人介绍,找到老周。去Z的店参观了一下,了解情况后。当时老周可能被蚊子叮昏了头脑,觉得这不简单吗,便答应Z老板说三天可以完成。不过,这做起来确实不复杂,基础代码当天晚上用了两个多小时就搞定了。串口发数据这事也不难,就一个 SerialPort 类就搞定的。协议方面有文档,一个字节数组,代入参数就行。每台拆片机的编组号和参数就用一人 Sqlite 数据库存放就完事,配上 EF Core 读写起来那简直是入门级的难度。

不过,在第一次实测时遇到一个问题,每台机器的参数是不同的,需要提供一个界面,让用户可以增/删/改/查。也就是说,机器参数不能用类来封装,静态语言又不能动态生成属性。当然,这也不是静态语言的错,而是思路的问题。我干吗非要用类封装呢?不封装不就更可以动态变化了吗?然后,老周的生理 CPU 飞速运转,眼前浮现着一张张熟悉的面孔—— 用字典来存储,用JSON来做,用XML来做……避免产生过多不必要的数据文件,老周决定在数据库加个表,一个选项(参数)就是一条数据记录。字段如选项名称,选项值,备注,添加时间,最后修改时间,添加人(谁操作的)等。

随后,又有问题了,虽然在数据库中我把选项(参数)值统一用文本来表示,但在用户界面上,总不能全放个 TextBox 在那里。最重要的是全用 TextBox 的话,验证的代码就要写很多了。比如:你输入的是日期吗?你输入的是整数吗?Bool 值的东西为什么还要让人填呢,直接CheckBox不好吗?现在的情况是,机器参数是用户动态添加的,在布局界面时我不能写死了,毕竟事先不能确定用下拉列表还是文本框。那就在运行时动态呈现控件吧。

思路有了,但方法有很多种。老周当初吹下了三天完工的牛皮,所以,创建新控件的思路可能更花时间,而且感觉也没必要。经过短暂的计划,老周的想法:

1、在编辑界面上用一个 ListBox 或 ItemsControl,这样可以免去许多排版的功夫。就把界面当成一个列表框控件,每个被编辑的选项就是一个列表项。这样添加和删除也方便,直接 Binding 就好了。

2、为 ItemsControl 定义列表项模板,是 DataTemplate,不是控件模板。重做控件模板跟创作新控件一样,费时间。

3、DataTemplate 中,一个 TextBlock 用来显示项目标签(不可修改的文本),然后值呢?

4、选项值用的控件是不固定的,事先不可知,老周就放了个 ContentControl 在那里,就当作占位符用吧。为什么选它呢?因为它有 Content 属性,可以放任何东西,而且配套一个 ContentTemplate 属性,类型正是 DataTemplate。当然,也可以用类似功能的控件。

老周的想法就是,用 ContentTemplate 去引用其他的数据模板,当然数据模板也不能写死的。即要定义多个模板,里面放不同的控件,需要根据选项的需求选择不同的模板。于是,有一个类可以用上——DataTemplateSelector。

这个类有一个虚方法叫 SelectTemplate,能够根据相同数据运态返回数据模板。派生类只要重写这个方法就 OK。

哦,补充一下,什么是拆片机。大伙伴看看你身上穿的战袍,是不是由一块块布组成?服装厂先要依据图纸,用选定的线织成一块块的“散片”,针织机有横机和纵机,横向的多见。以前是手动操作,现在是电脑控制。这些“散片”可交给缝盘工人(做缝盘的一般是女孩,以前那些手动织机的话,男女都有)“组装”起来。下图是常见的缝盘机(不是缝纫机,二者不同的),老周家里还有三台,23年前的型号,有两台还是全新未拆封的。

缝盘机的套口编号要与针织机的匹配使用,如果混用会出问题的,以前内销毛衣常见的12针(这个简单说就是代表线眼的疏密)一般会配用14号的缝盘机(当然也不是绝对,看工人经验,有时候接近编号的也行)。

从上世纪 90 年代起,老周家里做过十几年的毛衣加工,现在是租给别人做,近20台电脑横机,全天24小时工作。所以,服装方面的东西,老周还是懂一点点的。

拆片就是把编织好的衣片拆解,变回一筒一筒的毛线。这个原因就很复杂,可能针织时效果不好,可能拿错图纸了,可能多出来不用的……把衣片重新变回毛线,还可以重复用,不浪费。有些片可能被机器里的润滑油污染,以前有的师傅懒得处理,是直接不要的(在农村,以前有些人家用来生火煮水煮饭),不过,这些毛料燃烧起来是环境污染,而且味道让人很难受。现在很少有人这么干。毕竟,别说燃气灶,连电磁炉在农村都很普及了。直接生火做饭的很少,就算要生火,也会选一些天然的柴木。

拆片机结构很简单,用夹子固定衣片,先人工抽出部分丝线,在橡皮轮上缠绕二三十圈,然后开动电机就行,工作起来有点像打毛机。拆片机现在并没有标准的产品,都是个别有“本事”的工厂或者像Z先生这样的,自己做的。

------------------------------------------------------------------------------------------------------------------------------------------------------------------

不得了,这次扯的废话太长了。不能再说了,不然就真变成水文了。下面说重点。

步骤一:定义选项包装类

哦,老周上面只是说,不用类来封装选项数据,但每条选项记录还是要封装的。这个类与数据库中的选项表映射。为了简单,老周删除了像备注、操作员、时间、父级选项等无关的属性。

public class OptionItem : INotifyPropertyChanged
{private string _labelName;private string _objValue;private bool _required;private UIElementType _uiType;private string _listItems;public int Id { get; set; }/// <summary>/// 选项的标签文本/// </summary>public string LabelName{get => _labelName;set{_labelName = value;OnMyPropertyChanged();}}/// <summary>/// 选项的值/// </summary>public string ObjectValue{get { return _objValue; }set{_objValue = value;OnMyPropertyChanged();}}/// <summary>/// 是否为必填/// </summary>public bool Required{get => _required;set{_required = value;OnMyPropertyChanged();}}/// <summary>/// 界面控件类型/// </summary>public UIElementType UIType{get => _uiType;set{_uiType = value;OnMyPropertyChanged();}}/// <summary>/// 显示在下拉列表中的内容,只有需要下拉列表控件时才用到/// </summary>public string ListItems{get => _listItems;set{_listItems = value;OnMyPropertyChanged();}}// 属性更改后调用的方法private void OnMyPropertyChanged([CallerMemberName] string propertyName = null){if (string.IsNullOrEmpty(propertyName)){return;}PropertyChanged?.Invoke(this, new(propertyName));}// 属性更改通知事件public event PropertyChangedEventHandler PropertyChanged;
}

实现 INotifyPropertyChanged 接口,这个不用多介绍,可以让绑定对象能实时获得更改通知。UIElementType 是一个枚举类型,表示要呈现什么样的控件,映射到数据库表时用整型存储。

public enum UIElementType
{TextBox,                // 普通文本框NumberBoxInt,           // 文本框,但输入整数用NumberBoxFloat,         // 文本框,但输入浮点数用CheckBox,               // 复选框DropdownList,           // 下拉列表框DatePicker              // 日期选择器
}

这老周项目所需要用的控件,你可以根据实际添加成员。WPF的编辑控件其实很少,比 WinForms 还少。大概开发团队觉得 WPF 的控件可以自己设计。虽然控件模板方便换,但做起来也要一定工作量的,反正嘛,非必要不创作控件。有大伙伴会问:怎么不用开源的第三方控件?如果老周自己用的话,倒是可以的。可是项目一旦是商用的就……有些开源协议是很让人无语的,而且不少项目在商用上要授权的。比如那个 Qt,到处告人,“一不小心就会一团糟”。所以咱们这边做上位机、客户端什么的基本用 .NET,Qt 几乎没几个人用,很多公司都不敢用,怕被找上门。

购买授权这种事不要问老周,因为老周也搞不懂。但老周大胆怀疑,这些王X蛋是不是故意的,想通过打官司来发家致富?其实大伙常用的手机 App 表面免费,实际上你如果有心情去阅读一下用户协议,你会冒出一身冷汗。处处给你设坑,你想不跳都不行。比如微信输入法什么的,你如果用它来写小说,那小心,可能你的版权会变成别人的。还有一些不要脸的套壳 AI 服务,在你我不知情的前提下,把咱们的东西变成它们的数据、模型的一部分,产权归谁?科学技术很强大,可有没有质疑过,现在搞科技创新的初心是什么?为了割矮脚白菜?还是为战争服务?还是……

不过,老周从 2010 年至今,接的很多项目 90% 是用 .NET 做的,至少目前没出什么授权上的问题,也没收到过“绿尸寒”。微软还是靠谱的。

为了在数据库中能够兼容,表示选项值的 ObjectValue 属性定义为字符串类型,在数据库也是用文本存放。因为选项值可能是浮点数和日期,但文本很强大,啥值它都能表示。LabelName 属性是显示在用户界面上的,不能被编辑。Required 属性表示此字段值是不是必需的,如果是,会在标签旁边显示一个星号(*)。在绑定时,用 BoolValueConverter 转换器把 bool 值转为控件的 Visibility 属性值,这个转换器是 .NET 类库自有的,不用我们自己写。

 ListItems 属性只有当控件是 ComboBox 时才用到,字符串内容,每个项用逗号分隔,显示在下拉列表中。由于它的值是一个字符串,而 ComboBox 的 item source 是列表类型。需要写一个转换器,把字符串分割成一个数组。

public class StrToListConverter : IValueConverter
{public object Convert(object value, Type targetType, object parameter, CultureInfo culture){string list = (string)value;var splis = list.Split(',').Select(s => s.Trim());return splis.ToArray();}public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture){return null;}
}

因为绑定是单向的,所以 ConvertBack 不需要,返回 null 了事。

同样的道理,如果用的是 CheckBox 控件,需要 bool 和 string 之间的转换。

public class BoolValueConverter : IValueConverter
{public object Convert(object value, Type targetType, object parameter, CultureInfo culture){// 由于数据的值都用字符串表示,所以这里可以直接转成字符串string strValue = (string)value;if (bool.TryParse(strValue, out bool val)){return val;}return false;}public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture){// 转回去的时候,都是字符串return value.ToString();}
}

由于 CheckBox 控件用于编辑,需要双向绑定,所以 ConvertBack 方法要实现。

步骤二:从TextBox派生一个类

尽管原则上不创作新控件,但由于 TextBox 除输入任意文本外,有些选项只能让用户输入数字。有大伙伴会说,用 InputScope 不就行了吗。还真的不行。input scope 只对触控屏幕键盘有效,对于实体键盘无法限制。因此,为了方便,只好派生出一个类,然后重写 OnPreviewTextInput 方法,把非数字字符排除。其实,处理 TextBox 的 PreviewTextInput 事件也可以的,不过派生一个类来处理,完整性更好,也方便直接把控件代码复制到别的项目使用。Preview开头的事件是【隧道】事件,即从 XAML 树的外层向内引发,而 TextInput 事件是冒泡式的,从内向外引发。键盘事件由 WM_KEY*** 相关消息产生,操作系统会将其传递给窗口。窗口处理了再到里面的控件处理。我们应该处理 Preview 事件,当输入的字符不是数字时,不让它向下传播,这样 TextBox 就不会接收这个字符了。

public class NumberTextBox : TextBox
{public NumberTextBox(){TextNumberType = NumberType.Integer;// 禁用输入法InputMethod.SetIsInputMethodEnabled(this, false);// 设置输入范围是数字,这只对触控键盘有效InputScope ipscope = new();ipscope.Names.Add(new InputScopeName(InputScopeNameValue.Number));this.InputScope = ipscope;}/// <summary>/// 获取/设置数字类型/// </summary>public NumberType TextNumberType { get; set; }protected override void OnPreviewTextInput(TextCompositionEventArgs e){Debug.WriteLine($"Text={e.Text}, ControlText={e.ControlText}");string pattern = TextNumberType == NumberType.Integer ? "[0-9]+" : "[0-9.]+";
        var rgxres = Regex.Match(e.Text, pattern);if (!rgxres.Success){e.Handled = true;return;}base.OnPreviewTextInput(e);}
}public enum NumberType
{/// <summary>/// 整数/// </summary>
    Integer,/// <summary>/// 浮点数/// </summary>
    Floating
}

老周这里就用正则表达式来匹配,实际上它只匹配一个字符。只要有字符输入,TextInput 相关的事件就会引发,而关联的文本只是刚刚输入的那个字符,而不是 TextBox 中的所有字符。也就是说,这段代码只是限制,并不能验证输入的对不对。其实这代码还不严谨,如果用户已经输入过小数点了,也可能出现输入 N 个小数点的问题。我们也可以优化一下。

protected override void OnPreviewTextInput(TextCompositionEventArgs e)
{……if (TextNumberType == NumberType.Floating && e.Text == "."){// 看看他输入了几个小数点TextBox tb = (TextBox)e.OriginalSource;int index = tb.Text.LastIndexOf('.');// 索引如果有效,说明之前输入过小数点if(index > -1){e.Handled= true;return;}}base.OnPreviewTextInput(e);
}

e.Handled = true 会阻止事件向下传播,就能达到阻止输入某些字符的目的。注意,TextInput 相关事件引发时,一般我们只能获取刚输入的字符,要结合 TextBox 现有的文本来分析,就必须从 TextBox.Text 属性获取。上面代码是先判断当前输入的是浮点数,且当前输入的字符是小数点,如果是,就从 TextBox 现有文本中查找小数点。如果找到,说明之前输入过,就不能再输入了。

当然了,限制并不能代替数验证功能。如果需要,还要进一步用代码检查输入的值是否有效。

步骤三:准备一堆数据模板

要用模板选择器筛选要用的数据模板,首先得准备一系列待选模板,放进资源字典中。

<Window.Resources><!--转换器--><BooleanToVisibilityConverter x:Key="btvCvt" /><local:BoolValueConverter x:Key="boolValCvt"/><local:StrToListConverter x:Key="strToListCvt"/><!--下面几个模板是用于选择的--><DataTemplate x:Key="selTempAnyTxt"><TextBox Text="{Binding Path=ObjectValue, Mode=TwoWay}" InputMethod.IsInputMethodEnabled="False"/></DataTemplate>
    <DataTemplate x:Key="selTempNumberInt"><local:NumberTextBox Text="{Binding Mode=TwoWay, Path=ObjectValue}" TextNumberType="Integer"/></DataTemplate>
    <DataTemplate x:Key="selTempNumberFloat"><local:NumberTextBox Text="{Binding Mode=TwoWay, Path=ObjectValue}" TextNumberType="Floating"/></DataTemplate>    <DataTemplate x:Key="selTempList"><ComboBox ItemsSource="{Binding Path=ListItems, Converter={StaticResource strToListCvt}}"Text="{Binding Path=ObjectValue, Mode=TwoWay}"IsReadOnly="True"IsEditable="True"/></DataTemplate><DataTemplate x:Key="selTempCheckBox"><CheckBox IsChecked="{Binding Path=ObjectValue,Mode=TwoWay,Converter={StaticResource boolValCvt}}" Content=""/></DataTemplate>
    <DataTemplate x:Key="selTempDatePicker"><DatePicker Text="{Binding Path=ObjectValue, Mode=TwoWay}" SelectedDateFormat="Short"/></DataTemplate><!--END-->
……
</Window.Resources>

要定义一堆模板,看着复杂,其实很简单。

步骤四:编写模板选择器

    public class MyTemplateSelector : DataTemplateSelector{public override DataTemplate SelectTemplate(object item, DependencyObject container){OptionItem opt = (OptionItem)item;switch (opt.UIType){case UIElementType.TextBox:return TextTemplate;case UIElementType.NumberBoxInt:return IntNumTemplate;case UIElementType.NumberBoxFloat:return FloatNumTemplate;case UIElementType.DropdownList:return DropListTemplate;case UIElementType.CheckBox:return CheckBoxTemplate;case UIElementType.DatePicker:return DatePickerTemplate;}return TextTemplate;}#region 公共属性,用于引用模板public DataTemplate TextTemplate { get; set; }
        public DataTemplate IntNumTemplate { get; set; }public DataTemplate FloatNumTemplate { get; set; }public DataTemplate CheckBoxTemplate { get; set#endregion}

注意那六大属性,待会把选择器放到XAML资源中,可以引用我们前面定义的那些模板。重写 SelectTemplate 方法是核心。根据 UIType 属性来判断要用的模板。这是咱们前面定义选项类时用的枚举。

步骤五:套用

        <!--模板选择器--><local:MyTemplateSelector x:Key="tempSelt"TextTemplate="{StaticResource selTempAnyTxt}"IntNumTemplate="{StaticResource selTempNumberInt}"FloatNumTemplate="{StaticResource selTempNumberFloat}"DropListTemplate="{StaticResource selTempList}"CheckBoxTemplate="{StaticResource selTempCheckBox}"DatePickerTemplate="{StaticResource selTempDatePicker}"/><DataTemplate x:Key="itemTemp" DataType="local:OptionItem"><Grid MinWidth="300" HorizontalAlignment="Center" Margin="0,5"><Grid.ColumnDefinitions><ColumnDefinition Width="100"/><ColumnDefinition Width="*"/></Grid.ColumnDefinitions><StackPanel Orientation="Horizontal" Grid.Column="0" HorizontalAlignment="Right" Margin="0,0,5,0"><TextBlock><Run Text="{Binding Mode=TwoWay, Path=LabelName}"/><Run Text=":"/></TextBlock><TextBlock Visibility="{Binding Required, Converter={StaticResource btvCvt}}" Foreground="Red" FontSize="16">*</TextBlock></StackPanel><ContentControl Grid.Column="1" Content="{Binding}" ContentTemplateSelector="{StaticResource tempSelt}"/></Grid></DataTemplate>

Key 为 itemTemp 的模板是给 ItemsControl 控件用的。而前面的那些模板只是给 ContentControl 用的。也就是说,ItemsControl 控件的列表项套用 itemTemp 模板,而 itemTemp 模板里面的 ContentControl 控件又套用前面定义的模板(由模板选择器决定)。

注意,绑定 Required 属性的 TextBlock 只有一个“*”字符,当 Required 属性为true时,该控件显示星号,表示此字段必填。

步骤六:界面布局

在界面上放一个 ItemsControl 控件就能显示各个选项字段信息了。

<Grid><Grid.RowDefinitions><RowDefinition Height="*"/><RowDefinition Height="*"/></Grid.RowDefinitions><ScrollViewer Grid.Row="0"><ItemsControl x:Name="itOpt"ItemTemplate="{StaticResource itemTemp}"/></ScrollViewer><TextBox Grid.Row="1" x:Name="txtDisp"/>
</Grid>

txtDisp 用来每 3 秒显示一次选项类列表,这个只是用来观察绑定有没有双向更新,并无实际用途。

下面是代码部分。

    public partial class MainWindow : Window{private ObservableCollection<OptionItem> _optionItems = new();private DispatcherTimer timer = new DispatcherTimer();public MainWindow(){InitializeComponent();timer.Interval = TimeSpan.FromSeconds(3);timer.Tick += OnTimer;_optionItems.Add(new(){Id = 1,Required = true,LabelName = "banch",UIType = UIElementType.NumberBoxInt,ObjectValue = "3"});_optionItems.Add(new(){Id = 2,LabelName = "factor",UIType = UIElementType.NumberBoxFloat,ObjectValue = "0.1",Required = false});_optionItems.Add(new(){Id = 3,LabelName = "tcc1",ObjectValue = "s-i-2",Required = true,UIType = UIElementType.TextBox});_optionItems.Add(new(){Id = 4,LabelName = "tcc2",ObjectValue = "k9",Required = true,UIType = UIElementType.TextBox});_optionItems.Add(new(){Id = 5,LabelName = "wt_mode",ObjectValue = "nor",Required = false,UIType = UIElementType.DropdownList,// 下拉列表ListItems = "cls,nor,slw,wdw"});_optionItems.Add(new(){Id = 6,LabelName = "flash",UIType = UIElementType.CheckBox,ObjectValue = "True",Required = false});_optionItems.Add(new(){Id = 7,LabelName = "size",ObjectValue = "8",UIType = UIElementType.NumberBoxInt,Required = false});_optionItems.Add(new(){Id = 8,LabelName = "reg_0xD3",Required = false,ObjectValue = "29",UIType = UIElementType.NumberBoxInt});// 绑定itOpt.ItemsSource = _optionItems;timer.Start();}private void OnTimer(object sender, EventArgs e){StringBuilder bd = new StringBuilder();foreach (OptionItem oi in _optionItems){bd.AppendLine($"{oi.LabelName} = {oi.ObjectValue}");}txtDisp.Text = bd.ToString();}}

DispatchTimer 只是用来周期性更新显示,没其他用途。

 

运行程序后,你会发现。程序会根据各个选项的设置,生成编辑字段。

 是不是很好用呢?现在,把 factor 字段改为 1.5,等3秒钟后,看看有没有更改。

已经更新了。

再试试,把 flash 的 CheckBox 中的勾去掉,看会不会变成 false。

好了,已经有效果了,这样一来,用户爱添加啥参数就随他的便。

 

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

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

相关文章

OO第七,八次大作业总结

一、前言   在这个学期即将迎来尾声的时候,这个阶段的大作业也迎来了最后的两个迭代大作业,而本次博客就将围绕这两个迭代大作业讲述二、设计与分析  这两次的迭代作业的类设计其实没有很多的变化,只不过根据题目要求添加了互斥开关和受控窗帘,二极管这几个类,其中互斥…

微信内置H5支付

🧑‍💻 写在开头 点赞 + 收藏 === 学会🤣🤣🤣场景是用户通过微信扫app内的收款码,跳到一个h5页面。然后完成支付。 代码实现的整体流程: 使用微信扫码,码是app内生成的,码的内容是一个h5页面链接,扫码完成后跳转到自定义的h5支付界面。 扫码进入后,将页面展示所…

《编译原理》阅读笔记:p25-p32

《编译原理》学习第 5 天,p25-p32总结,总计 8 页。 一、技术总结 1.lexical lexical这个单词后续会经常用到,所以首先要搞懂它的英文意思,不然看到中文的“词法,语法,文法”这三个词的时候就会懵了——lexical对应这三个里面的哪一个? (1)lexical: lexicon + al,加…

OOP七,八次作业总结

OOP四到六次作业总结 一.前言: 第七八次为家庭电路分析程序。 在第七次作业中,家庭电路系统,匹配类设计不当 在第八次作业中,我修改了输出类,并优化类的设计 二,设计与分析: 1.家居强电电路模拟程序-3(第七次作业) 在本次作业中,我对类的设计较为直白,输出类也没有…

findfont: Font family Times New Roman not found.

这是因为在python环境中的matplotlib文件夹下没有这个字体的文件。 对于windows系统,请参考:https://blog.csdn.net/qq_49323609/article/details/139026798 Macos系统:先打开软件:找到字体的路径然后模仿以上https://blog.csdn.net/qq_49323609/article/details/139026798…

模拟集成电路设计系列博客——8.2.1 环形振荡器

8.2.1 环形振荡器 在这一章节,我们将介绍振荡器的基本概念。环路振荡器可以分成若干种,但两种主要的分类依据是直接产生正弦信号还是产生方波(或者三角波)信号输出。正弦波输出振荡器常被用于一些频率选择或者反馈电路的调谐电路,而方波输出振荡器常被用于一个非线性反馈电…

分类器

网络模型分为特征提取器,包括一系列卷积层。池化层、激活函数; 分类器则是后面的全连接层; 对于全连接层直接输出的值为logits;logits也叫做模型输出的对数几率,$n_j$ 通常表示为模型对于第 j 类的输出值,也就是在进行Softmax函数转换之前的原始logits

Graph Neural Networks based Log Anomaly Detection and Explanation论文阅读笔记

1.介绍 现代高科技系统,如云服务器或高性能计算机,通常由大量的组件组成。随着时间的推移,这些系统变得越来越复杂,使得手动系统操作和维护变得困难甚至不可行[17]。因此,自动化系统操作和维护是非常可取的。为了实现这一点,系统日志被普遍用于记录系统状态和重要事件。通…

Miniconda安装使用说明

Anaconda这安装包体积真是劝退我了https://docs.anaconda.com/miniconda/miniconda是最小的conda安装环境,只有conda+python+pip+zlib和一些其他常用的包,体格不到100Mb,非常迷你。 Miniconda 使用教程 创建和管理环境 Conda 允许用户创建隔离的环境,以避免不同项目之间的依…

m基于GA遗传优化的高斯白噪声信道SNR估计算法matlab仿真

1.算法仿真效果 matlab2022a仿真结果如下:2.算法涉及理论知识概要基于遗传算法(Genetic Algorithm, GA)的高斯白噪声信道(Additive White Gaussian Noise, AWGN)信噪比(Signal-to-Noise Ratio, SNR)估计方法是一种利用生物进化原理进行全局优化的技术,旨在寻找最优解,…

重生之我在男航学Java-3(完结)

一、前言家居强电电路模拟程序-3 考查内容:类的设计(适应迭代以及合理的类间关系的设计),正则表达式的应用(如何正确解析输入),java中集合框架的熟悉与使用并且选择合理的集合框架(存储数据并且方便数据的增删改查) 新增内容:互斥开关,落地窗帘 本次PTA由于自身的原…

嵌入式计算和视觉加速的开放标准

嵌入式计算和视觉加速的开放标准 https://www.khronos.org/assets/uploads/developers/presentations/Khronos_Embedded_Compute_and_Vision_Overview_Jun24.pdf Khronos将软件连接到硅 开放、免版税的互操作性标准,以利用GPU、XR和多处理器硬件的力量3D图形、增强和虚拟现实、…

第三次Blog作业

题目集6-7的总结性Blog 一、前言 题目集总结 第六次题目集 知识点:控制理论、电路设计、设备工作原理 题量:中等 难度:中等偏上控制设备部分涉及对开关、分档调速器、连续调速器三种设备的理解和操作。需要理解开关的两种状态,分档调速器的档位变化以及连续调速器的连续调节…

第三次blog

第三次blog感悟 随着知识越学越多,任务也越来越繁重,难度也是与日俱增,也许是时间花得还不够也不够认真导致最近的一些pta作业都完成得差强人意,我认为java的学习最重要的是写作业的认真、严谨的逻辑以及大把的时间。nchu-software-oop-2024-上-6 本次作业题目大致内容 1、…

第三次PTA作业总结

一.第七和第八次PTA作业总结 1.第七次PTA作业的分析 (1).设计思路: 设计电路设备类(如ControlDevice, AdjustableDevice, ExclusiveSwitch)和受控设备类(Light, Fan, Curtain)来封装设备的属性和行为。 电路类(SequentialCircuit, ParallelCircuit)用于表示电路结构,…

在WPF中使用着色器

概念类比范畴 CPU GPU二进制文件 .exe .cso / .ps二进制指令 机器码 CSO(shader指令)助记符 汇编 SL高级语言 C# HLSL高级语言文件 .cs .hlsl / .fx高级语言编译器 csc.exe fxc.exeAPI .NET API DirectX API运行时环境 CLR DirectX调试工具 Visual Studio Debugger RenderDoc着…

OOP第三次博客作业

目录前言:设计与分析:opp-7-家居强电电路模拟程序-2opp-8-家居强电电路模拟程序-2踩坑心得:opp-5-家居强电电路模拟程序-3踩坑和心得:opp-5-家居强电电路模拟程序-4踩坑和心得:总结: 前言: oop-7相比与oop-6仅增加了两个电子元件,一个互斥开关,一个受控窗帘,除了优化…

《DNK210使用指南 -CanMV版 V1.0》第五章 编译CanMV固件

第五章 编译CanMV固件 1)实验平台:正点原子DNK210开发板 2) 章节摘自【正点原子】DNK210使用指南 - CanMV版 V1.0 3)购买链接:https://detail.tmall.com/item.htm?&id=782801398750 4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/k210/ATK-…

第三次PTA总结

前言 本阶段面向对象程序设计进行了两次PTA训练,两次都是关于电路设计的迭代。迭代次数越多难度越大,后期事情较多,作业和考试任务重、题目的难度也较大,所以没有拿到每次作业的满分,但是都根据题目的变化对自己的设计进行了一定的改变和优化。 知识点类的设计; 数组、链…