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

构建现代化WPF应用:数据驱动开发与高级特性解析

启动时默认打开哪个界面是在App.xaml的StartupUri属性中设置。

Window标签

x:Class起到了部分类的作用,让XAML与CS文件做关联,起到了映射的作用。

xmlns是XML NameSpace的简称,起到了命名控件的作用,与代码中命名空间不同的是,它的值是一个URL,这样做的好处是可以将多个命名空间合并到一个URL里。

xmlns后面的字母是不同的命名空间的前缀,后续如果需要显示静态变量,自定义控件时会用到它。比如:Title="{x:Static local:FeedbackWindow.MyTitle}",将FeedbackWindow的MyTitle静态变量显示了出来;在使用评分控件时,需要在控件的名称前添加命名空间的前缀hc:<hc:Rate x:Name="myRate"></hc:Rate>

布局

StackPanel

StackPanel和Winform里的Panel很相似,默认是垂直布局,也可以水平局部,还可以互相嵌套。

Grid

Grid是窗体的根元素,它的作用和HTML的Table标签很相似,可以定义水平和垂直单元的个数,然后在各个单元中放置各个控件。

RowDefinitions- 像大楼一样,一层一层的堆叠,浏览网页就是水平展示的,从上到下显示

<!-- 布局 -->
<Grid.RowDefinitions><RowDefinition Height="0.2*"></RowDefinition><RowDefinition Height="0.8*"></RowDefinition>
</Grid.RowDefinitions>

ColumnDefinitions - 像火车头一样,从左到右显示

<!-- 水平布局 -->
<Grid.ColumnDefinitions><ColumnDefinition Width="0.35*"></ColumnDefinition><ColumnDefinition Width="0.65*"></ColumnDefinition>
</Grid.ColumnDefinitions>

值得注意的是,XAML与HTML的区别之处还在于,在使用了Grid之后,在将其他元素放到Grid中时不是直接放到它的内部,而是外部,并通过Grid.Column/Row=Num来标记这个内容是放在哪儿。

比如在定义一个Border控件的时候,需要在控件的标签里添加这个属性:

<!-- 右侧背景色 -->
<Border Grid.Column="1" CornerRadius="5" Background="WhiteSmoke">
</Border>

这是在Grid的第2列单元格中定义了一个Border,背景色是白色。

资源

在编写XAML的时候会发现在许多控件中有着重复的属性,使用资源标签就可以将它们抽离出来,合并到一起,起到简化代码的作用。它类似于HTML中的CSS,将同一类型控件的样式放到<style>标签中,使用的时候告诉控件指定样式的名字即可。

1、定义资源

可以在3个不同的地方定义资源:在当前界面中,在程序入口文件中,在资源文件中。

在当前页面中定义:

<Window.Resources><SolidColorBrush x:Key="myColor1" Color="Red"></SolidColorBrush>
</Window.Resources>

定义资源需要用到Key属性,相当于HTML标签的id属性,是用来标记的,标签名称SolidColorBrush是控件类型,Color=Red是属性的键值对。

在程序入口文件App.xaml中定义:

<Application.Resources><ResourceDictionary><!-- 定义资源 --><SolidColorBrush x:Key="myColor2" Color="Orange"></SolidColorBrush></ResourceDictionary>
</Application.Resources>

在资源文件中定义:

首先我们要新建一个资源字典,然后在里面定义资源

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><SolidColorBrush x:Key="myColor3" Color="Yellow"></SolidColorBrush>
</ResourceDictionary>

同时还得在App.xaml中引入该资源文件:

<Application.Resources><ResourceDictionary><ResourceDictionary.MergedDictionaries><!-- 引入外部资源文件 --><ResourceDictionary Source="/ColorDictionary.xaml"/></ResourceDictionary.MergedDictionaries></ResourceDictionary>
</Application.Resources>

2、使用资源

使用资源比声明要简单一些,只需在需要用到的属性的值里面添加{},并在里面输入StaticResource或DynamicResource,再输入一个控件,后面再跟上资源的Key值即可。

<Border Grid.Row="1" Grid.Column="0" Background="{StaticResource myColor3}"></Border>
<Border Grid.Row="1" Grid.Column="1" Background="{DynamicResource myColor4}"></Border>

StaticResource和DynamicResource的区别在于一个不能修改,一个可以修改。

一般修改的逻辑会写在cs文件中:

private void Button_Click(object sender, RoutedEventArgs e)
{// 将资源进行修改,可以看到只有动态资源可以修改,静态的不行,这个在一些需要切换状态的场景中会用到Resources["myColor4"] = new SolidColorBrush(Color.FromRgb(30, 70, 120));Resources["myColor3"] = new SolidColorBrush(Color.FromRgb(30, 70, 120));
}

使用Resource[资源的Key值] = 目标值,即可完成修改。

样式

介绍完了资源之后,就不得不提到样式,样式是把资源集合化了,它可以包含多个样式。

在当前页面中定义样式:

<Window.Resources><Style x:Key="buttonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}"><Setter Property="Width" Value="180"></Setter><Setter Property="Height" Value="35"></Setter><Setter Property="FontSize" Value="18"></Setter><Setter Property="Foreground" Value="White"></Setter></Style>
</Window.Resources>

应用样式:


<Button Margin="0 50 0 0" Background="Transparent" Style="{StaticResource buttonStyle}">注册</Button>

最初在应用样式的时候发现一个问题,就是明明没有修改按钮的背景色,悬浮背景色以及边框,但是它却自动被修改了,问了下AI原来是系统的默认行为,想要只应用Setter中的样式,需要在添加 BasedOn="{StaticResource {x:Type Button}}去继承Button的样式。

控件模板

控件模板顾名思义就是将多个具有相似之处的模板抽离成一个模板,比如一个表单中,最常见的一个模板就是一个文本+输入框。

它也是一种资源,所以需要像前面的样式一样去定义一个资源然后使用它

1、定义模板

<Window.Resources><ControlTemplate x:Key="myTemplate" TargetType="{x:Type TextBox}"><StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Top"><TextBlock Margin="0 10" Text="{TemplateBinding Tag}"></TextBlock><TextBox Height="33" Width="200"></TextBox></StackPanel></ControlTemplate>
</Window.Resources>

如果要使用模板,需要使用ControlTemplate标签,Key是唯一标识,TargetType是使用模板的控件的类型。标签内部就是模板体了,里面是一个文本和一个输入框,输入框的Text值是从使用模板的属性Tag中去取。

2、使用模板

<StackPanel><TextBox Height="33" Width="400" Tag="用户名: " Template="{ }"></TextBox>
</StackPanel>

在使用模板时,需要定义和模板的TargetType相同类型的控件,然后使用Template属性,里面的值和上一节使用样式时一样,在{}中写【资源类型】【资源名称】。

数据绑定

绑定基础

数据绑定是MVVM,模型的核心之一,它与Winform中以事件驱动的模型不同,实现了在界面里控件的属性(官方说法称之为特征值)发生改变后,会自动影响到实现了Model类的实例的属性(官方说法称之为源)。

绑定方向有双向绑定,顾名思义就是控件或者类有一个发生改变都会立即同步;还有一种是单向绑定,有两个方向,控件发生改变会通知类,但类改变不会影响控件,亦或者反过来;最后一种是只绑定一次,就是在首次加载时。

另外还有绑定的触发时机也分两种,一种是控件属性发生改变后立即生效,一种是控件失去焦点时生效。

实现绑定还有一个前提是需要类实现INotifyPropertyChanged接口,并在属性的Setter方法里调用它。

1、生成一个类,并实现INotifyPropertyChanged,修改默认的Setter方法,代码块:propfull。

public class Employee : INotifyPropertyChanged
{private string name;public string Name{get { return name; }set { name = value; if (this.PropertyChanged != null){this.PropertyChanged(this, new PropertyChangedEventArgs(nameof(Name)));}}}public event PropertyChangedEventHandler? PropertyChanged;
}

2、在后台cs文件里将类与控件绑定,这个是在初始化控件完成后进行的

// 开始绑定,首先声明一个绑定对象,可以给它设置类的源头和要绑定到哪个属性上
var binding = new Binding();
binding.Source = _employee;
binding.Path = new PropertyPath("Name");// 设置绑定的方向,是双向绑定(默认)- TwoWay,单向绑定-OneWay,OneWayToSource,还有只绑定一次-OneTime,单向绑定又分为两种,从类绑定到界面-OneWay;从界面绑定到类-OneWayToSource
binding.Mode = BindingMode.Default;// 设置绑定的触发器,默认是PropertyChanged,但这种方式在应用在输入框时更新过于频繁,推荐设置为LostFocus,在失去焦点时更新
binding.UpdateSourceTrigger = UpdateSourceTrigger.Default;// 最后是设置控件的属性,并将它与类的关联起来
this.EmployeeName.SetBinding(TextBox.TextProperty, binding);

控件间的绑定

控件间的绑定就是一个控件的属性发生改变后,立即影响另外一个控件,只需在XAML中编写相关代码。

在控件的特征值里指定源和属性,比如下面的例子中是在一个TextBox控件的Text属性中指定名为HeightSlider控件的Value属性。

<!-- 将滑动控件的Value值绑定到TextBox的Text属性里 -->
<TextBox x:Name="TextBoxHeight" BorderBrush="Black"  Height="50" Text="{Binding Path=Value, ElementName=HeightSlider}"/>
<Slider Name="HeightSlider" Height="50" Margin="0 20 0 0" Minimum="0" Maximum="100" IsSnapToTickEnabled="True"></Slider>

数据上下文绑定

数据上下文绑定(DataContext Binding)也是在XAML中就可以完成的绑定操作。它是在Window.DataContext标签中声明源,属性,属性值。


<Window x:Class="XCYN.NET8.WPF.ControlBindWindow"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:XCYN.NET8.WPF"mc:Ignorable="d"Title="ControlBindWindow" Height="450" Width="800">
<Window.DataContext><model:Employee Name="张三"></model:Employee>
</Window.DataContext>
<Grid><!-- 通过DataContext的方式进行绑定,这种方式不用再后台编写代码,需要声明一个Window.DataContext标签,在里面声明源和特征值 --><TextBox Text="{Binding Name}" BorderBrush="Black" Height="44"></TextBox>
</Grid>

列表绑定

列表绑定是最常用的绑定方式了,简单的说就是将一个List数组绑定到列表控件中,类似于Winform中的DataGridView。

它有两种方式,显示指定DisplayMemberPath和不显示指定,但需要额外编写<ListBox.ItemTemplate>和<DataTemplate>标签。

第一种方式使用起来比较简单,相对的可以做的更少一些,可以用于简单的列表展示;第二种要复杂一些,但也能做更复杂的操作。

第一种方式

声明一个ListBox控件,在CodeBehind生成数据源

<ListBox Height="300" x:Name="ListBoxEmployee"></ListBox>

    List<Employee> list = new List<Employee>(){new Employee(){Id = "1",Name = "张三",Address = "湖北省武汉市"},new Employee(){Id = "2",Name = "李四",Address = "湖南省长沙市"},new Employee(){Id = "3",Name = "王五",Address = "广东省东莞市"}};this.ListBoxEmployee.ItemsSource = list;this.ListBoxEmployee.DisplayMemberPath = "Name";

这里完成了对ListBox的数据绑定和属性的指定,这里指定的是Name属性,待会会显示在列表中。

第二种方式

声明一个ListBox控件,在CodeBehind生成数据源,在ListBox控件里声明ListBox.ItemTemplate标签,在这个标签里再声明DataTemplate标签,最后在这里关联源的属性。

  <ListBox Height="300" x:Name="ListBoxEmployee"><ListBox.ItemTemplate><DataTemplate><StackPanel Orientation="Horizontal"><TextBlock Text="{Binding Path=Id}" Width="50" Margin="5"></TextBlock><TextBlock Text="{Binding Path=Name}"  Width="100" Margin="5"></TextBlock><TextBlock Text="{Binding Path=Address}"  Width="150" Margin="5"></TextBlock></StackPanel></DataTemplate></ListBox.ItemTemplate></ListBox>

这里绑定了三个TextBlock,分别指定ID,Name,Address属性。

    List<Employee> list = new List<Employee>(){new Employee(){Id = "1",Name = "张三",Address = "湖北省武汉市"},new Employee(){Id = "2",Name = "李四",Address = "湖南省长沙市"},new Employee(){Id = "3",Name = "王五",Address = "广东省东莞市"}};this.ListBoxEmployee.ItemsSource = list;

相对绑定

自身绑定

自身绑定是以控件自身既作为源也作为控件去使用源的属性。

<Button Width="100" Content="登录" FontSize="18" Height="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Width}"></Button>

上面的例子是以Width为源的特征值,显示在Height属性中,需要使用RelativeSource并指定它的Mode为Self。

父级绑定

父级绑定是以控件的父级为源,将里面的特征值显示在子级控件里。

<Grid Background="LightPink"><Grid Background="AliceBlue" Height="300" Width="500"><StackPanel><Button Width="100" Content="登出" FontSize="18" Height="100" Background="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorLevel=2,AncestorType=Grid}, Path=Background}"></Button></StackPanel></Grid>
</Grid>

需要使用RelativeSource并指定它的Mode为FindAncestor,同时也要指定层级关系AncestorLevel,控件类型AncestorType。

转换器

转换器的作用是将无法直接显示在属性里的值,比如枚举类型,转换为可以在属性里显示的类型。

首先我们要生成一个转换器的类并继承IValueConverter接口,Convert方法是正向转换,ConvertBack是反向转换,这里只实现了正向转换,将JobIcon枚举类型转为字符串类型。

    class JobIconConvert : IValueConverter{public object Convert(object value, Type targetType, object parameter, CultureInfo culture){var obj = (JobIcon)value;switch (obj){case JobIcon.ZS:return "Image/战士.png";case JobIcon.MS:return "Image/牧师.png";case JobIcon.FS:return "Image/法师.png";case JobIcon.XD:return "Image/小德.png";case JobIcon.QS:return "Image/骑士.png";default:return null;}}public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture){throw new NotImplementedException();}}

在XAML中需要在资源里声明该转换器,然后在用到这个枚举类型的属性里使用它

<Window.Resources><model:JobIconConvert x:Key="jobConvert"></model:JobIconConvert>
</Window.Resources>
<Grid><StackPanel><TextBlock Text="请选择你的职业" Height="50" FontSize="28"></TextBlock><ListBox x:Name="listBox_zy" Height="300"><ListBox.ItemTemplate><DataTemplate><StackPanel Orientation="Horizontal"><TextBlock Text="{Binding Path=Name}" Margin="5"></TextBlock><Image Margin="5" Source="{Binding Path=Icon,Converter={StaticResource jobConvert}}"></Image></StackPanel></DataTemplate></ListBox.ItemTemplate></ListBox></StackPanel>
</Grid>

在CodeBehind中只是简单地初始化源和进行数据绑定。

    list = new List<WowJob>(){new WowJob(){Name = "战士", Icon = JobIcon.ZS},new WowJob(){Name = "牧师", Icon = JobIcon.MS},new WowJob(){Name = "法师", Icon = JobIcon.FS},new WowJob(){Name = "小德", Icon = JobIcon.XD},new WowJob(){Name = "骑士", Icon = JobIcon.QS},};this.listBox_zy.ItemsSource = this.list;

多路绑定

多路绑定是将多个源绑定到一个控件中,比如在注册用户名时,需要输入两次密码,才能通过验证,实现它和转换器类似,需要一个实现了IMultiValueConverter接口的类去做验证。

    class PasswordConvert : IMultiValueConverter{/// <summary>/// 验证两个密码是否相同./// </summary>public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture){var arr = Array.ConvertAll(values, m => m.ToString());if (arr.Length == 2 &&arr[0] == arr[1] &&arr[0].Length > 0){return true;}return false;}public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture){throw new NotImplementedException();}}

编写XAML,新建两个输入框和按钮,按钮默认是无法使用的状态,当两个密码是相同的时变为可用。

<StackPanel><StackPanel Orientation="Horizontal" Margin="5"><TextBlock Text="密码" Width="50" Margin="5"></TextBlock><TextBox Name="txt_pwd1" Width="200"></TextBox></StackPanel><StackPanel Orientation="Horizontal" Margin="5"><TextBlock Text="新密码" Width="50" Margin="5"></TextBlock><TextBox Name="txt_pwd2" Width="200"></TextBox></StackPanel><Button x:Name="btn_register" Content="注册" IsEnabled="False" HorizontalAlignment="Left" Margin="5"></Button>
</StackPanel>

最后是在CodeBehind中,进行多路绑定,有点小复杂,首先以两个输入框作为源,里面的Text属性作为Path,将它们添加到MultiBinding中,给这个实例设置为单向绑定,给它设置转换器,就是刚才新建的,最后是给按钮控件设置绑定的属性和绑定实例。

    // 生成控件的绑定对象,这里是把它们作为源了,然后把它们添加到多组绑定对象中,并设置它们的转换器,在转换器内进行数据验证var binding1 = new Binding("Text"){Source = this.txt_pwd1};var binding2 = new Binding("Text"){Source = this.txt_pwd2};var multiBinding = new MultiBinding(){Mode = BindingMode.OneWay};multiBinding.Bindings.Add(binding1);multiBinding.Bindings.Add(binding2);multiBinding.Converter = new PasswordConvert();// 最后给目标控件设置要控制的属性和绑定对象this.btn_register.SetBinding(Button.IsEnabledProperty, multiBinding);

依赖属性

依赖属性是在普通属性的基础上,让类继承自DependencyObject,可以通过propdp代码块生成的该属性片段。由于它是通过类似单例模式的方式去注册对象,所以起到了节省资源的效果,比如:如果创建多个依赖对象,它们未显示指定的一个属性值是会被共享的,这样就节省了内存的开销;并且所有实例都是共享同一套元数据(如默认值,回调函数等),而不是每个单独的实例去存储这些;当依赖属性不再使用时,WPF会自动清除相关资源,避免内存泄漏。

在WPF中所有的UI控件都是依赖对象,依赖属性默认是支持绑定的,无需再去继承INotifyPropertyChanged去实现绑定。

依赖属性是通过HashTable去维护对象,这种数据结构是一种“以时间换空间”的结构。

1、创建依赖对象

    class Student : DependencyObject{public int Age{get { return (int)GetValue(AgeProperty); }set { SetValue(AgeProperty, value); }}// Using a DependencyProperty as the backing store for Age.  This enables animation, styling, binding, etc...public static readonly DependencyProperty AgeProperty =DependencyProperty.Register("Age", typeof(int), typeof(Student), new PropertyMetadata(0));}

2、将依赖对象绑定到控件中,可以看到它是支持绑定的,在界面中显示了18

    var binding = new Binding();var student = new Student() { Age = 18 };binding.Source = student;binding.Path = new PropertyPath("Age");this.myButton.SetBinding(Button.ContentProperty, binding);

附加属性

附加属性经常会用到,在之前使用Grid进行布局时就用到过,在StackPanel中就用到了Grid.Column来定位控件,在自定义时同样需要继承自DependencyObject,并通过propa来快速生成该属性。

    class School : DependencyObject{public static string GetGrade(DependencyObject obj){return (string)obj.GetValue(MyGradeProperty);}public static void SetGrade(DependencyObject obj, string value){obj.SetValue(MyGradeProperty, value);}// Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...public static readonly DependencyProperty MyGradeProperty =DependencyProperty.RegisterAttached("Grade", typeof(string), typeof(School), new PropertyMetadata(""));}

这里定义了一个School的Grade附加属性,接下来将把这个属性附加到Student中,这样就可以做到不改变Student的情况下,让它可以使用Grade这个属性,实现了开闭原则。

    // 使用自定义的附加属性去设置和获取值Student student = new Student(){Age = 18,};School.SetGrade(student, "一年级");var grade = School.GetGrade(student);

下面是使用WPF的控件的附加属性,实现拖动滑块后让矩形块上下左右移动的代码片段。

<StackPanel><Slider x:Name="xLocationSlider" Margin="5" Minimum="0" Maximum="200"></Slider><Slider x:Name="yLocationSlider"  Margin="5" Minimum="0" Maximum="200"></Slider><Canvas><!-- Rectangle位于Canvas画布的内部,就可以使用它的附加属性,然后通过绑定对附加属性进行控制 --><Rectangle Margin="5" Width="50" Height="50" Fill="BlueViolet" Canvas.Left="{Binding ElementName=xLocationSlider, Path=Value}" Canvas.Top="{Binding ElementName=yLocationSlider, Path=Value}"></Rectangle></Canvas>
</StackPanel>

路由事件

路由事件是一种消息接收方法,它不同于Winform那种点对点的事件触发,它是在一个控件触发事件后,将事件不断地往外层传递,直到有钩子接收到该事件。

首先我们要给钩子的控件取个名字root,然后给发出事件的控件取个名字。

<Grid x:Name="root"><StackPanel><Button x:Name="btn_submit" Content="提交" Margin="5"></Button></StackPanel>
</Grid>

接着在CodeBehind中,在控件初始化完毕后注册一个钩子,这里是给Button的Click注册了一个事件,接收方是root。

    // 通过对最外层的Grid控件调用AddHandler方法完成事件的注册,第一个参数不同类型的控件的事件,这里是Button按钮的点击事件// 第二个参数是事件触发时调用的委托,这里使用lambda表达式来定义委托,委托中可以获取到触发事件的控件this.root.AddHandler(Button.ClickEvent, new RoutedEventHandler((m, n) => {// OriginalSource属性可以获取到触发事件的控件var element = n.OriginalSource as FrameworkElement;MessageBox.Show(element?.Name);// 也可以将sender参数进行转换,获取接收事件的控件var sender = m as FrameworkElement;MessageBox.Show(sender?.Name);}));

路由命令

路由命令比起路由事件更加具体,因为它显示的指定了绑定的控件名称,因此更好控制,不过使用起来更加复杂。

首先在XAML中创建控件

<Grid x:Name="root"><StackPanel><TextBox x:Name="txt_name" Width="200" Height="50" Margin="5"></TextBox><Button x:Name="btn_clear" Width="100" Height="40" Margin="5" Content="清除"></Button></StackPanel>
</Grid>

然后在CodeBehind中声明一个命令,并将命令的名称和当前类的类型传递过去

/// <summary>
/// 声明一个路由命令,第一个参数是命令的名称,第二个参数是该命令属于哪个类.
/// </summary>
private RoutedCommand command = new RoutedCommand("myEvent", typeof(RoutedCommandWindow));

最后是将该命令绑定到控件中

    // 为命令指定源和目标this.btn_clear.Command = this.command;this.btn_clear.CommandTarget = this.txt_name;// 创建命令的Bindingvar binding = new CommandBinding();binding.Command = this.command;binding.CanExecute += (m, n) =>{// 是否执行命令if (this.txt_name.Text.Length > 0){n.CanExecute = true;}else{n.CanExecute = false;}n.Handled = true;};binding.Executed += (m, n) =>{// 如何执行命令this.txt_name.Text = "";n.Handled = true;};// 何处接收命令,一般在上层元素中this.root.CommandBindings.Add(binding);

相关文章:

构建现代化WPF应用:数据驱动开发与高级特性解析

启动时默认打开哪个界面是在App.xaml的StartupUri属性中设置。 Window标签 x:Class起到了部分类的作用&#xff0c;让XAML与CS文件做关联&#xff0c;起到了映射的作用。 xmlns是XML NameSpace的简称&#xff0c;起到了命名控件的作用&#xff0c;与代码中命名空间不同的是&a…...

MATLAB实现振幅调制(AM调制信号)

AM调制是通信专业非常重要的一个知识点。今天我们使用MATLAB编程实现AM调制。 我们实现输入一个载波信号的频率与调制信号的频率后&#xff0c;再输入调幅度&#xff0c;得到已调信号的波形与包络信号的波形&#xff0c;再使用FFT算法分析出已调信号的频谱图。 源代码&#x…...

loss = -F.log_softmax(logits[:, -1, :], dim=1)[0, irrational_id]

loss = -F.log_softmax(logits[:, -1, :], dim=1)[0, irrational_id] 解释这行代码 loss = -F.log_softmax(logits[:, -1, :], dim=1)[0, irrational_id] 的具体含义和背后的数学原理。 1. 代码拆解与功能 这行代码的核心是计算负对数似然损失(Negative Log Likelihood Los…...

NSSCTF [HNCTF 2022 WEEK4]

题解前的吐槽&#xff1a;紧拖慢拖还是在前段时间开始学了堆的UAF(虽然栈还没学明白&#xff0c;都好难[擦汗])&#xff0c;一直觉得学的懵懵懂懂&#xff0c;不太敢发题解&#xff0c;这题算是入堆题后一段时间的学习成果&#xff0c;有什么问题各位师傅可以提出来&#xff0c…...

基于springboot+vue的医院门诊管理系统

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat12开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;Maven3.3.9 系统展示 系统登录 系统首…...

大模型越狱:技术漏洞与安全挑战——从原理到防御

近年来&#xff0c;随着大模型能力的飞速提升&#xff0c;其安全性问题日益受到关注。其中&#xff0c;“大模型越狱”&#xff08;Model Jailbreaking&#xff09;成为热议焦点——指通过特定手段绕过模型的安全限制&#xff0c;诱导其生成有害、违法或超出设计范围的内容。本…...

Linux 常用命令 -hostnamectl【主机名控制】

简介 hostnamectl 命令中的 “hostname” 顾名思义&#xff0c;指的是计算机在网络上的名称&#xff0c;“ctl” 是 “control” 的缩写&#xff0c;意味着控制。hostnamectl 命令用于查询和修改系统主机名以及相关的设置。它通过与 systemd 系统管理器交互&#xff0c;允许用…...

《Python星球日记》 第72天:问答系统与信息检索

名人说&#xff1a;路漫漫其修远兮&#xff0c;吾将上下而求索。—— 屈原《离骚》 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 一、问答系统概述1.问答系统的工作原理2. 问答系统的典型应用场景 二、问答系统…...

VUE3 -综合实践(Mock+Axios+ElementPlus)

目录 前言 目标 1.工程创建 2.Mock 2.1 配置Mock 扩 展 2.2 定义模拟数据 2.3 创建Mock服务器 3.导入ElementPlus 4.表格页面搭建 5.动态路由跳转 6.详情页面的制作 前言 基于前文 VUE3详细入门&#xff0c;我们对VUE3的基本使用有了初步的了解&#xff0c;下…...

Qt原型模式实现与应用

在Qt中实现原型模式&#xff08;Prototype Pattern&#xff09;可以通过以下步骤完成。该模式的核心是通过克隆现有对象来创建新对象&#xff0c;而非通过传统的构造函数。以下是详细说明和示例&#xff1a; 1. 原型模式的核心概念 目的&#xff1a;避免重复初始化对象的高成本…...

语音识别-2

上一篇关于语音识别, 虽然能用,但在系统适配,机器适配方面,速度,性能等还是有优化的地方.所以这篇是关于这些的. 1.蓝牙优化 A2DP:是一种单向的高品质音频数据传输链路,通常用于播放立体声音乐;SCO: 则是一种双向的音频数据的传输链路,该链路只支持8K及16K单声道的音频数据…...

ElasticSearch深入解析(十二):聚合——分桶聚合、指标聚合、管道子聚合

文章目录 一、分桶聚合1. 分桶聚合的核心逻辑与核心类型2. 分桶聚合的高级特性 二、指标聚合1. 指标聚合的核心逻辑与基础类型&#xff08;1&#xff09;基础统计指标&#xff08;单值输出&#xff09;&#xff08;2&#xff09;复合统计指标&#xff08;多值输出&#xff09; …...

互联网大厂Java求职面试:AI内容生成平台下的高并发架构设计与性能优化

互联网大厂Java求职面试&#xff1a;AI内容生成平台下的高并发架构设计与性能优化 场景背景&#xff1a; 郑薪苦是一名经验丰富的Java开发者&#xff0c;他正在参加一家匿名互联网大厂的技术总监面试。这家公司专注于基于AI的内容生成平台&#xff0c;支持大规模用户请求和复杂…...

论MCU如何在Fatfs中使用Flash接口的方法

前提&#xff1a; MCU移植了FS&#xff0c;如FATFSOSFMount工具 OSFMount或者其他磁盘工具用于挂载.img镜像&#xff0c;可格式化文件系统打开并放入实际使用的文件 步骤 1. cmd命令建立空.img镜像&#xff0c;以下为12MB fsutil file createnew fat.img 120000002. OSFMo…...

Python+Selenium爬虫:豆瓣登录反反爬策略解析

1. 引言 在当今互联网时代&#xff0c;数据抓取&#xff08;爬虫&#xff09;技术广泛应用于数据分析、市场调研、自动化测试等领域。然而&#xff0c;许多网站采用动态加载技术&#xff08;如Ajax、React、Vue.js等框架&#xff09;来渲染页面&#xff0c;传统的**<font s…...

nt!MiDispatchFault函数分析之第一次循环前后的变化

第一部分&#xff1a;nt!MiDispatchFault函数分析之第一次循环之前 1: kd> !pte 0x002bf810 VA 002bf810 PDE at C0300000 PTE at C0000AFC contains 7B314867 contains 00000000 pfn 7b314 ---DA--UWEV not valid 1: kd> dd C0000AFC…...

JMeter性能测试工具使用

JMeter是一款强大的性能测试工具&#xff0c;由Java编写&#xff0c;小巧轻便&#xff0c;最关键的是开源免费&#xff0c;现在已经成了主流的性能测试工具。 下面介绍一下基本的安装使用、高级功能及可视化实时图表展示&#xff0c;带你们感受一下JMeter的世界~ 1、安装 1.…...

Windows 环境下安装 Node 和 npm

安装 Node.js 和 npm https://nodejs.org/zh-cn/download 执行 fnm install 22 之后&#xff0c;执行 node 或 npm 提示找不到命令 fnm env 看环境变量 找到 node 和 npm 命令在 C:\Users\HUAWEI\AppData\Roaming\fnm\node-versions\v22.15.0\installation 目录下&#xff0…...

开发指南112-样式的优先级别

在前端样式设置里&#xff0c;界面元素一般会多个地方进行定义和影响。一般而言&#xff0c;CSS样式的优先级如下&#xff1a; ‌1、内联样式‌&#xff1a;style属性中定义的样式&#xff0c;具有最高的优先级。 ‌2、ID选择器‌&#xff1a;通过ID选择器指定的样式&#xff…...

单向通信机制EventSource

EventSource 是浏览器提供的一种实现服务器推送 简称 SSE 基于 HTTP 协议的单向通信机制 可以通过服务器将实时数据推送到客户端 而不需要客户端不断发起请求EventSource 和 WebSocket 都可以实现服务器向客户端的实时数据推送&#xff0c;但它们有不同的适用场景&#xff1a;E…...

PyTorch中mean(dim=1)的深度解析

mean(dim=1) 是什么意思 在自然语言处理中,文本经过分词器处理后会转换为token序列,每个token对应一个向量表示。mean(dim=1) 的作用是在序列维度上对这些向量取平均,将整个序列压缩为单个向量。下面我用具体例子解释: 1. 张量的维度结构 假设我们有一个输入文本:"…...

Xcode报错:“Set `maskView` to `nil` before adding it as a subview of ZFMaskView

Assertion failure in -[ZFMaskView _addSubview:positioned:relativeTo:] 嗯&#xff0c;坑爹的IOS18&#xff0c;当你基于UIView实现的自己的子类中定义一个属性并初始化时就会出现崩溃&#xff01; /// 遮罩property (nonatomic, strong) UIView *maskView; 因为UIVIEW本…...

uniapp -- 验证码倒计时按钮组件

jia-countdown-verify 验证码倒计时按钮组件 一个用于发送短信验证码的倒计时按钮组件&#xff0c;支持自定义样式、倒计时时间和文本内容。适用于各种需要验证码功能的表单场景。 代码已经 发布到插件市场 可以自行下载 下载地址 特性 支持自定义按钮样式&#xff08;颜色、…...

e.g. ‘django.db.models.BigAutoField‘.

在Django框架中&#xff0c;django.db.models.BigAutoField 是一个用于数据库模型的字段类型&#xff0c;它用于自动增长的ID字段。这个字段类型特别适用于需要处理大量数据的应用&#xff0c;比如在大型网站或应用中&#xff0c;普通的 AutoField 可能不足以存储增长的ID值&am…...

【​​HTTPS基础概念与原理​】对称加密与非对称加密在HTTPS中的协作

在HTTPS通信中&#xff0c;对称加密和非对称加密协同工作&#xff0c;共同保障数据的机密性和密钥交换的安全性。以下是两者的协作机制及RSA、ECDHE等算法的核心作用&#xff1a; 一、对称加密与非对称加密的分工 1. 对称加密&#xff08;如AES、ChaCha20&#xff09; • 作用&…...

ESP系列单片机选择指南:结合实际场景的最优选择方案

前言 在物联网(IoT)快速发展的今天&#xff0c;ESP系列单片机凭借其优异的无线连接能力和丰富的功能特性&#xff0c;已成为智能家居、智慧农业、工业自动化等领域的首选方案。本文将深入分析各款ESP芯片的特点&#xff0c;结合典型应用场景&#xff0c;帮助开发者做出最优选择…...

使用Thrust库实现异步操作与回调函数

使用Thrust库实现异步操作与回调函数 在Thrust库中&#xff0c;你可以通过CUDA流(stream)来实现异步操作&#xff0c;并在适当的位置插入回调函数。以下是如何实现的详细说明&#xff1a; 基本异步操作 Thrust本身并不直接暴露CUDA流接口&#xff0c;但你可以通过以下方式使…...

【Python 异常处理】

Python 的异常处理机制是构建健壮程序的核心工具&#xff0c;通过 try-except 结构实现优雅的错误管理。以下是系统化指南&#xff1a; 一、基础异常处理结构 try:# 可能出错的代码result 10 / 0 except ZeroDivisionError:# 异常处理逻辑print("错误&#xff1a;除数不…...

40:相机与镜头选型

第一章 相机 1.1 理论基础 1.1.1 相机分类 1 &#xff09;按照芯片类型&#xff1a; CCD 相机、 CMOS 相机 2 &#xff09;按照传感器的结构特性&#xff1a;线阵相机、面阵相机 3 &#xff09;按照扫描方式&#xff1a;隔行扫描相机、逐行扫描相机 4 &#xff09;按…...

【ESP32-S3】Guru Meditation Error 崩溃分析实战:使用 addr2line 工具 + bat 脚本自动解析 Backtrace

【ESP32-S3】Guru Meditation Error 崩溃分析实战&#xff1a;使用 addr2line 工具 bat 脚本自动解析 Backtrace 在使用 ESP32-S3 进行开发时&#xff0c;我们常常遇到串口报错&#xff0c;例如&#xff1a; Guru Meditation Error: Core 1 paniced (LoadProhibited). Exce…...

win11 VSCode 强制弹窗微软登录

今天在一台新电脑上配置VSCode同步的时候&#xff0c;用了微软账号&#xff0c;因为这台电脑比较特殊&#xff0c;不方便科学上网&#xff0c;所以一开始用的微软账户登录&#xff0c;导致和GitHub账号登录的配置、扩展等等不同步。 后面准备改用GitHub账号登录发现不行&#…...

Thrust库中的Gather和Scatter操作

Thrust库中的Gather和Scatter操作 Thrust是CUDA提供的一个类似于C STL的并行算法库&#xff0c;其中包含两个重要的数据操作&#xff1a;gather(聚集)和scatter(散开)。 Gather操作 Gather操作从一个源数组中按照指定的索引收集元素到目标数组中。 函数原型&#xff1a; t…...

springboot + mysql8降低版本到 mysql5.7

springboot mysql8降低版本到 mysql5.7 <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.49</version></dependency>spring:datasource:driverClassName: com.mysql.jdbc.D…...

在 Windows 中配置使用 WSL 来运行 Linux 环境,主要有以下步骤:

一、安装 WSL 方法一&#xff1a;使用 wsl --install 命令 &#xff1a;以管理员身份运行 PowerShell 或 Windows 命令提示符&#xff0c;输入 wsl --install 命令&#xff0c;该命令将自动启用运行 WSL 所需的功能&#xff0c;并安装默认的 Linux 发行版 Ubuntu。 方法二&…...

TypeScript泛型:从入门到精通的全方位指南

TypeScript泛型&#xff1a;从入门到精通的全方位指南 前言 最近在社区看到很多小伙伴对TypeScript的泛型概念感到困惑。作为一名从Java转战前端的老兵&#xff0c;我想用最接地气的方式&#xff0c;带大家彻底搞懂这个看似高深实则简单的重要特性。 一、什么是泛型&#xf…...

DA14531如何在固件中生成与时间相关的mac和版本号

一. 蓝牙device information service显示固件编译时间 这里我是用序列号的characteristic来显示。 只需要把序列号的characteristic value用宏的方式&#xff1a; #define APP_DIS_SERIAL_NB_STR (__DATE__" "__TIME__) #define APP_DIS_SERIAL_NB_STR…...

内存安全设计方案

内存安全设计方案 1. 内存问题分析 1.1 常见内存问题 内存泄漏: 单例对象持有过多引用缓存未及时清理线程池资源未释放内存溢出: 大对象频繁创建队列积压并发处理不当GC频繁: 对象创建过多内存碎片化大对象分配1.2 问题场景 #mermaid-svg-uPgkoDPv6GNGT28v {font-family:&…...

免费Ollama大模型集成系统——Golang

Ollama Free V2 Web 功能实现&#xff1a;界面交互与后端逻辑 一、Web 界面概述 Ollama Free V2 的 Web 界面提供了丰富的交互功能&#xff0c;包括模型选择、图片上传、历史记录查看等。界面使用 Bootstrap 进行布局&#xff0c;结合 JavaScript 实现动态交互。 二、前端界…...

工具学习_模糊测试

定义&#xff1a;模糊测试&#xff08;fuzz testing, fuzzing&#xff09;是一种软件测试技术。其核心思想是将自动或半自动生成的随机数据输入到一个程序中&#xff0c;并监视程序异常&#xff0c;如崩溃、断言失败&#xff0c;以发现可能的程序错误&#xff0c;比如内存泄漏。…...

AI智能分析网关V4周界入侵检测算法精准监测与智能分析,筑牢周界安全防线

一、方案背景​ 随着安全防范需求的不断提升&#xff0c;传统周界安防系统存在误报率高、响应迟缓、智能化程度低等问题&#xff0c;难以满足现代化安全管理的要求。AI智能分析网关V4集成先进的人工智能算法与高性能计算能力&#xff0c;能够实现对周界区域的精准监测与智能分…...

ubuntu20.04系统搭建k8s1.28集群-docker作为容器运行时

ubuntu系统搭建 ubuntu-22.04.5-desktop-amd64.iso映像文件--->实际却是20.4focal版本。 【安装过程没有特别指出的默认回车下一步】 【用户和密码设置】 【网络连接】 【在vmware上安装的话&#xff0c;网络配置如下】【在vm里配置选择nat或者桥接即可】 【国内源配置】&…...

安全合规检查开源项目ComplianceAsCode/content详解及操作系统新产品开发适配指南

I. ComplianceAsCode/content简介 A. 项目使命及其在自动化合规中的重要性 ComplianceAsCode/content项目致力于为各类操作系统发行版和产品提供安全与合规内容。该项目的核心目标是促进自动化安全扫描和配置验证,从而取代传统的手动审计方法,这与日益增长的“合规即代码”…...

Jmeter -- JDBC驱动连接数据库超详细指南

数据库性能决定应用成败&#xff01;高峰期&#xff0c;慢查询拖垮系统&#xff1f;并发用户激增导致连接超时&#xff1f;这些问题让开发者头疼不已。Apache JMeter作为性能测试神器&#xff0c;不仅能测试Web应用&#xff0c;还能直连数据库&#xff0c;模拟多用户负载&#…...

R利用spaa包计算植物/微生物的生态位宽度和重叠指数

一、生态位宽度 生态位宽度指数包括shannon生态位指数和levins生态位指数。下面是采用levins方法计算生态位宽度。method也可以选择“shannon”。 二、生态位重叠指数 生态位重叠指数&#xff0c;包括levins生态位重叠指数、schoener生态位重叠指数、petrai…...

《AI大模型应知应会100篇》第62篇:TypeChat——类型安全的大模型编程框架

第62篇&#xff1a;TypeChat——类型安全的大模型编程框架 摘要 在构建 AI 应用时&#xff0c;一个常见的痛点是大语言模型&#xff08;LLM&#xff09;输出的不确定性与格式不一致问题。开发者往往需要手动解析、校验和处理模型返回的内容&#xff0c;这不仅增加了开发成本&a…...

STM32 片上资源之串口

STM32 片上资源之串口 1 串口介绍1.1 初步介绍1.2 主要特性1.2.1 USART特性1.2.2 UART特性 1.3 主要寄存器1.4 波特率计算1.5 常用工作模式1.5.1 轮询模式&#xff1a;1.5.2 中断模式&#xff1a;1.5.3 DMA模式&#xff1a; 1.6 常见应用1.7 注意事项 2 软件层面协议2.1 基本概…...

全球首个投影机息屏显示专利授权:九天画芯重新定义设备交互与节能显示新范式

一、从 “功能闲置” 到 “持续交互”—— 投影机专利授权开启显示技术新纪元 在智能设备高速发展的今天&#xff0c;投影机作为重要的显示终端&#xff0c;长期面临 “非观影时段功能闲置” 的行业痛点。2025 年&#xff0c;一项名为 “投影机息屏显示” 的核心基础专利获得授…...

音频分类的学习

1.深度学习PyTorch入门-语音分类 https://blog.csdn.net/sinat_41787040/article/details/129795496 https://github.com/musikalkemist/pytorchforaudio https://github1s.com/musikalkemist/pytorchforaudio/blob/main/04%20Creating%20a%20custom%20dataset/urbansoundda…...

Java—— 可变参数、集合工具类、集合嵌套

可变参数 说明 1. 可变参数本质上就是一个数组 2. 作用&#xff1a;在形参中接收多个数据 3. 格式&#xff1a;数据类型...参数名称 举例:int...a 4. 注意事项&#xff1a; 形参列表中可变参数只能有一个 可变参数必须放在形参列表的最后面 案例演示 …...

AGI大模型(15):向量检索之调用ollama向量数据库

这里介绍将向量模型下载到本地,这里使用ollama,现在本地安装ollama,这里就不过多结束了。直接从下载开始。 1 下载模型 首先搜索模型,这里使用bge-large模型,你可以根据自己的需要修改。 点击进入,复制命令到命令行工具中执行。 安装后查看: 2 代码实现 先下载ollama…...