上文讲到Avalonia中比较多的便利性,今天我们来讲一下自定义控件
- 研究了个把礼拜Avalonia,发现生态并不是很完善
首先是国内.NET人数少,且市场占据率也低,导致Avalonia相关的文档和讲授视频也少
其次是对于Avalonia这个新事务来讲,控件库不完善,固然官方提供了很多控件库,也有其他一些控件库,但是照旧有很多控件没有,例如,富文本编辑器,word,报表,流媒体控件好像官方必要付费才能使用.....
在这个情况下,由于本身行业和之前项目的关系,有效到流媒体控件,必要调用摄像头来出现影像,但是找了一圈发现并没有满足的控件....
那我们应该怎么办呢,没办法,只能手撸一个,话不多说,先上效果图,左边是开启的视频窗口,右侧为收罗的帧画面
那这个效果是怎么实现的呢,我们必要了解几个点
- 影像是什么
首先我们必要知道相机或者说摄像头捕获的影像是什么,是一帧一帧的画面,你也可以理解为照片,一帧即一张照片。那知道了这个我们就清楚,影像无非就是连续帧画面播放出来的效果,也就是一帧一帧的画面切换,形成了我们眼中看到的视频影像
- 怎样自定义控件
自定义控件分两种,第一种就是用空模板从零开始创建一个控件,第二个就是基于已有控件来定义本身想要的用户控件
话不多说,开干,这里操作影像使用的库是OpenCvSharp4,在你的项目中引入下面的包,根据本身平台引入对应的runtime包,这里我使用的是win平台测试
这里可以看到,我们定义了IsOpenCamera来控制是否开启摄像头,CurrentBitmap为当前帧画面。
我们还需监听一下这个IsOpenCamera的状态来控制视频的捕捉,在构造函数中有这么一句代码
- public Camera()
- {
- InitializeComponent();
- this.GetObservable(IsOpenCameraProperty).Subscribe(OnIsOpenCameraChanged);
- }
复制代码 在构造函数中我们需注入属性的监听来执行某些变乱
在开启摄像头变乱StartCamera中我们使用了线程来循环执行视频捕捉变乱,通过捕捉每一帧的画面,更新到Image控件上,实现视频的实时预览。
接下来,我们在别的地方使用这个控件
- <UserControl xmlns="https://github.com/avaloniaui"
- 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"
- mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
- xmlns:local="using:GeneralPurposeProgram.Controls"
- xmlns:vm="using:GeneralPurposeProgram.ViewModels.UserViewModels"
- x:DataType="vm:HomeViewModel"
- x:>
- <Design.DataContext>
- <vm:HomeViewModel></vm:HomeViewModel>
- </Design.DataContext>
- <Grid ColumnDefinitions="*,300">
- <Grid Grid.Column="0" RowDefinitions="50,300,*">
- <StackPanel Spacing="20" Grid.Row="0" Orientation="Horizontal">
- <Button Content="开始摄像头" HotKey="F5" Command="{Binding StartCameraCommand}" Margin="0,0,0,10" Width="150" />
- <Button Content="关闭摄像头" HotKey="F6" Command="{Binding StopCameraCommand}" Margin="0,0,0,10" Width="150" />
- <Button Content="采集图像" HotKey="F10" Command="{Binding CaptureFrameCommand}" Margin="0,0,0,10" Width="150" />
- </StackPanel>
- <StackPanel Orientation="Horizontal" Grid.Row="1">
- <local:Camera x:Name="CameraVideo"
- IsOpenCamera="{Binding IsOpenCamera,Mode=TwoWay}"
- CurrentBitmap="{Binding PreviewImage,Mode=TwoWay}" />
- </StackPanel>
- </Grid>
- <Grid Grid.Column="1">
- <ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
- <ListBox ItemsSource="{Binding Images}">
- <ListBox.ItemTemplate>
- <DataTemplate>
- <Image Source="{Binding}" Height="260" Stretch="Uniform" />
- </DataTemplate>
- </ListBox.ItemTemplate>
- </ListBox>
- </ScrollViewer>
- </Grid>
- </Grid>
- </UserControl>
复制代码- public class HomeViewModel : ViewModelBase
- {
- private WriteableBitmap? _previewImage;
- public WriteableBitmap? PreviewImage
- {
- get => _previewImage;
- set => this.RaiseAndSetIfChanged(ref _previewImage, value);
- }
- private ObservableCollection<WriteableBitmap> _images = [];
- public ObservableCollection<WriteableBitmap> Images
- {
- get => _images;
- set => this.RaiseAndSetIfChanged(ref _images, value);
- }
- public ReactiveCommand<Unit, Unit> StartCameraCommand { get; }
- public ReactiveCommand<Unit, Unit> StopCameraCommand { get; }
- public ReactiveCommand<Unit, Unit> CaptureFrameCommand { get; }
- private bool _isOpenVideo = false;
- public bool IsOpenVideo
- {
- get => _isOpenVideo;
- set => this.RaiseAndSetIfChanged(ref _isOpenVideo, value);
- }
- public HomeViewModel()
- {
- StartCameraCommand = ReactiveCommand.Create(StartCamera);
- StopCameraCommand = ReactiveCommand.Create(StopCamera);
- CaptureFrameCommand = ReactiveCommand.Create(CaptureFrame);
- Images = [];
- }
- private void StartCamera()
- {
- IsOpenVideo = true;
- }
- private void CaptureFrame()
- {
- if (PreviewImage != null && IsOpenVideo)
- {
- Images.Add(PreviewImage);
- }
- }
- private void StopCamera()
- {
- IsOpenVideo = false;
- }
- }
复制代码 通过上面的完备使用代码可以看出,我们前面注册的视频控件的两个属性IsOpenCamera和CurrentBitmap直接暴露给了父控件,通过变乱修改IsOpenCamera的值就能实现视频的开启和关闭。收罗图像则只必要将CurrentBitmap当前帧画面保存起来,存入Images集合中给ListBox体现出来即完成了采图功能。
相信大家看到这应该都能理解里面的原理了,通过捕捉摄像头的帧画面,一帧一帧更新到Image控件上,其实和动画、漫画一样。
鉴于上期便利性在这补充一点,相对于WPF来讲,Avalonia可以更方便的给按钮绑定键盘Key来触发变乱,只必要加上HotKey="Key"即可
可以看到,我在这绑定了F5、F6、F10键,当然,也可以绑定复合案件,例如HotKey="Ctrl+F5"。
好了,本文就讲到这,后续博主还会出一些自定义控件的合集,我本人是有筹划想手搓一个word文档编辑器的,但如今照旧想法,不确定能不能行,这是个工作量很大的工作,祝我好运吧。由于平时要上班,博主大概率是在周末更新。
都看到这了,不点个赞再走吗
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
|