c# Avalonia 架构开发跨平台应用

Avalonia,读:阿瓦隆尼亚

由于以前的c#开发的windows平台项目想移植到信创平台(UOS,Kylin)上,起初想用python重写,后来发现了这个Avalonia,用这个改动起来工作相对较少于是就先了解一下。

官网Avalonia Docs | Avalonia Docs (avaloniaui.net)

实现了一个计算器的应用,先看在不同平台的效果

windows11上

ubuntu上

统信UOS 上

麒麟 kylin v10 

 好了,先说一下问题,如果想一套代码在不同平台同时运行,里面调用的逻辑还是要分系统的,先分linux系统和windows系统,macOS等,然后不同系统里面还要再细分,如linux下的ubuntu,kylin,uos等,这里主要说一下在linux系统上,经常出错的一个问题就是下面的:

 Could not create glyphTypeface. 

Unhandled exception. System.InvalidOperationException: Could not create glyphTypeface. Font family: $Default (key: ). Style: Normal. Weight: Normal. Stretch: Normal
   at Avalonia.Media.Typeface.get_GlyphTypeface()
   at Avalonia.Rendering.Composition.Compositor.get_DiagnosticTextRenderer()
   at Avalonia.Rendering.Composition.Compositor.CreateCompositionTarget(Func`1 surfaces)
   at Avalonia.Rendering.Composition.CompositingRenderer..ctor(IRenderRoot root, Compositor compositor, Func`1 surfaces)
   at Avalonia.Controls.TopLevel..ctor(ITopLevelImpl impl, IAvaloniaDependencyResolver dependencyResolver)
   at Avalonia.Controls.WindowBase..ctor(IWindowBaseImpl impl, IAvaloniaDependencyResolver dependencyResolver)
   at Avalonia.Controls.WindowBase..ctor(IWindowBaseImpl impl)
   at Avalonia.Controls.Window..ctor(IWindowImpl impl)
   at Avalonia.Controls.Window..ctor()
   at GetStartedApp.MainWindow..ctor() in D:\working\c#_test\GetStartedApp\MainWindow.axaml.cs:line 10
   at GetStartedApp.App.OnFrameworkInitializationCompleted() in D:\working\c#_test\GetStartedApp\App.axaml.cs:line 18
   at Avalonia.AppBuilder.SetupUnsafe()
   at Avalonia.AppBuilder.Setup()
   at Avalonia.AppBuilder.SetupWithLifetime(IApplicationLifetime lifetime)
   at Avalonia.ClassicDesktopStyleApplicationLifetimeExtensions.StartWithClassicDesktopLifetime(AppBuilder builder, String[] args, Action`1 lifetimeBuilder)
   at GetStartedApp.Program.Main(String[] args) in D:\working\c#_test\GetStartedApp\Program.cs:line 12
已放弃 (核心已转储)

主要原因是加载的字体不存在就报bug了。刚上也有自己安装字体的解决方法,参见

http://t.csdnimg.cn/4otvKicon-default.png?t=N7T8http://t.csdnimg.cn/4otvK但是上文没有我试过这么多系统

最好的方法是在每个系统中使用已经自带的字体。改代码Program.cs如下

using Avalonia;
using Avalonia.Media; 
using System;
using System.Drawing.Text;
using System.Linq;
using System.Runtime.InteropServices;

namespace CalculatorApp;

class Program
{
    [STAThread]
    public static void Main(string[] args) => BuildAvaloniaApp()
                .StartWithClassicDesktopLifetime(args);

    // BuildAvaloniaApp 是应用程序的启动方法,负责配置并启动 Avalonia 应用程序。
    public static AppBuilder BuildAvaloniaApp()
    {
        // 初始化默认的字体名称为空字符串
        string defaultFont = "";

        // 检查当前操作系统是否是 Linux 系统
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
        {
            // 获取当前操作系统的描述信息,通常包含操作系统的名称和版本
            string osDescription = RuntimeInformation.OSDescription.ToLower();
            Console.WriteLine("osDescription: " + osDescription);

            // 检查操作系统描述是否包含 "uniontech",如果是,表示是 UOS 系统
            if (osDescription.Contains("uniontech"))
            {
                // 设置默认字体为 "Noto Sans"(这是 UOS 系统中常见的字体)
                defaultFont = "Noto Sans";
            }
            // 检查操作系统描述是否包含 "kylin",如果是,表示是麒麟 v10 系统
            else if (osDescription.Contains("kylin"))
            {
                // 设置默认字体为 "Arial"(麒麟系统中常用的字体)
                defaultFont = "Arial";
            }
            // 检查操作系统描述是否包含 "ubuntu",如果是,表示是 Ubuntu 系统
            else if (osDescription.Contains("ubuntu"))
            {
                // 设置默认字体为 "Noto Mono"(Ubuntu 中常用的等宽字体)
                defaultFont = "Noto Mono";
            }
        }

        // 创建 FontManagerOptions 对象,并设置默认的字体名称
        FontManagerOptions options = new FontManagerOptions
        {
            DefaultFamilyName = defaultFont // 通过操作系统检测结果设置的默认字体
        };

        // 输出当前使用的字体信息到控制台,以便调试和验证
        Console.WriteLine("Using font: " + options.DefaultFamilyName);

        // 返回一个 AppBuilder 实例,配置并启动 Avalonia 应用程序
        return AppBuilder.Configure<App>()      // 配置应用程序
            .UsePlatformDetect()                // 自动检测运行平台(Windows, Linux, macOS)
            .WithInterFont()                    // 配置默认字体为 InterFont,作为默认字体集
            .LogToTrace()                       // 允许日志信息输出到控制台,方便调试
            .With(options);                     // 应用字体选项
    }
}

只有上面这个代码配好了,后面的逻辑在各个linux平台上才没有问题。

下面写出界面代码  ,文件名 MainWindow.axaml,其后缀为axaml与wpf中常用的xaml多个a表示使用的是Avalonia架构。这个代码定义了一个简洁的计算器界面,使用 Avalonia 框架构建。通过数据绑定和命令模式,实现了将界面操作与业务逻辑分离的设计。

<Window xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        x:Class="CalculatorApp.MainWindow"
        Title="手搓计算器"
        Width="350" Height="650"
        MinWidth="300" MinHeight="580"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:CalculatorApp"
        mc:Ignorable="d"
        x:DataType="local:MainWindowViewModel"
        Background="#F0F0F0"
        WindowStartupLocation="CenterScreen"
		KeyDown="Window_KeyDown">
	<!-- 设置窗体居中 -->

	<!-- 主布局容器 -->
	<Grid Margin="10">
		<Grid.RowDefinitions>
			<RowDefinition Height="100"/>
			<!-- 设置显示屏的行高度 -->
			<RowDefinition Height="40"/>
			<!-- 设置结果显示行的高度 -->
			<RowDefinition Height="100"/>
			<!-- 预留的一行(可以放其他功能) -->
			<RowDefinition Height="*"/>
			<!-- 按钮行,占用剩余空间 -->
		</Grid.RowDefinitions>

		<!-- 显示屏,显示输入的数字和操作 -->
		<Grid Grid.Row="0">
			<!-- 显示输入的数字,右对齐,字体大小为 40 -->
			<Label Name="DisplayAll" FontSize="40" Content="{Binding DisplayAll}" HorizontalContentAlignment="Right" VerticalContentAlignment="Center"/>
		</Grid>

		<!-- 显示当前计算结果 -->
		<Grid Grid.Row="1">
			<!-- 显示计算结果,右对齐,字体大小为 30 -->
			<Label Name="DisplayResult" FontSize="30" Content="{Binding DisplayResult}" HorizontalContentAlignment="Right" VerticalContentAlignment="Center"/>
		</Grid>

		<!-- 按钮区域,设置按钮布局 -->
		<Grid Grid.Row="3">
			<!-- 定义按钮的行 -->
			<Grid.RowDefinitions>
				<RowDefinition Height="1*"/>
				<!-- 每行高度相等,使用比例分配 -->
				<RowDefinition Height="1*"/>
				<RowDefinition Height="1*"/>
				<RowDefinition Height="1*"/>
				<RowDefinition Height="1*"/>
			</Grid.RowDefinitions>

			<!-- 定义按钮的列 -->
			<Grid.ColumnDefinitions>
				<ColumnDefinition Width="1*"/>
				<!-- 每列宽度相等,使用比例分配 -->
				<ColumnDefinition Width="1*"/>
				<ColumnDefinition Width="1*"/>
				<ColumnDefinition Width="1*"/>
			</Grid.ColumnDefinitions>

			<!-- 第一行按钮 -->
			<Button Content="C" Grid.Row="0" Grid.Column="0" Classes="clear" Command="{Binding ClearCommand}"/>
			<!-- 清除按钮,绑定清除命令 -->
			<!-- 暂时未添加的功能按钮 -->
			<!-- <Button Content="±" Grid.Row="0" Grid.Column="1" Command="{Binding NegateCommand}"/>-->
			<!--<Button Content="%" Grid.Row="0" Grid.Column="2" Command="{Binding PercentCommand}"/>-->
			<Button Content="÷" Grid.Row="0" Grid.Column="3" Classes="operator" Command="{Binding AddDigitOrOperationCommand}" CommandParameter="/"/>
			<!-- 除法按钮,绑定操作命令 -->

			<!-- 第二行按钮 -->
			<Button Content="7" Grid.Row="1" Grid.Column="0" Command="{Binding AddDigitOrOperationCommand}" CommandParameter="7"/>
			<!-- 数字 7 -->
			<Button Content="8" Grid.Row="1" Grid.Column="1" Command="{Binding AddDigitOrOperationCommand}" CommandParameter="8"/>
			<!-- 数字 8 -->
			<Button Content="9" Grid.Row="1" Grid.Column="2" Command="{Binding AddDigitOrOperationCommand}" CommandParameter="9"/>
			<!-- 数字 9 -->
			<Button Content="×" Grid.Row="1" Grid.Column="3" Classes="operator" Command="{Binding AddDigitOrOperationCommand}" CommandParameter="*"/>
			<!-- 乘法按钮 -->

			<!-- 第三行按钮 -->
			<Button Content="4" Grid.Row="2" Grid.Column="0" Command="{Binding AddDigitOrOperationCommand}" CommandParameter="4"/>
			<!-- 数字 4 -->
			<Button Content="5" Grid.Row="2" Grid.Column="1" Command="{Binding AddDigitOrOperationCommand}" CommandParameter="5"/>
			<!-- 数字 5 -->
			<Button Content="6" Grid.Row="2" Grid.Column="2" Command="{Binding AddDigitOrOperationCommand}" CommandParameter="6"/>
			<!-- 数字 6 -->
			<Button Content="−" Grid.Row="2" Grid.Column="3" Classes="operator" Command="{Binding AddDigitOrOperationCommand}" CommandParameter="-"/>
			<!-- 减法按钮 -->

			<!-- 第四行按钮 -->
			<Button Content="1" Grid.Row="3" Grid.Column="0" Command="{Binding AddDigitOrOperationCommand}" CommandParameter="1"/>
			<!-- 数字 1 -->
			<Button Content="2" Grid.Row="3" Grid.Column="1" Command="{Binding AddDigitOrOperationCommand}" CommandParameter="2"/>
			<!-- 数字 2 -->
			<Button Content="3" Grid.Row="3" Grid.Column="2" Command="{Binding AddDigitOrOperationCommand}" CommandParameter="3"/>
			<!-- 数字 3 -->
			<Button Content="+" Grid.Row="3" Grid.Column="3" Classes="operator" Command="{Binding AddDigitOrOperationCommand}" CommandParameter="+"/>
			<!-- 加法按钮 -->

			<!-- 第五行按钮 -->
			<Button Content="0" Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2" Command="{Binding AddDigitOrOperationCommand}" CommandParameter="0" HorizontalAlignment="Stretch"/>
			<!-- 数字 0,占两列 -->
			<Button Content="." Grid.Row="4" Grid.Column="2" Command="{Binding AddDigitOrOperationCommand}" CommandParameter="."/>
			<!-- 小数点按钮 -->
			<Button Content="=" Grid.Row="4" Grid.Column="3" Classes="equals" Command="{Binding EqualsCommand}"/>
			<!-- 等于按钮,绑定等于命令 -->
		</Grid>
	</Grid>
</Window>

MainWindow.axaml.cs的代码

这个代码在 Avalonia UI 框架下,实现了按键输入处理功能。通过判断用户按下的键来触发计算器的相应操作,例如输入数字、执行加减乘除等操作,并通过 ViewModel 中的命令绑定来更新界面和执行计算逻辑。

using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Remote.Protocol.Input;
using System;
using Key = Avalonia.Input.Key;  // 为避免与其他命名空间中的 Key 冲突,显式定义 Key

namespace CalculatorApp
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();  // 初始化组件(加载 XAML UI)
            DataContext = new MainWindowViewModel();  // 设置数据上下文为 MainWindowViewModel,进行数据绑定
        }

        // 处理按键事件的方法,当用户按下键盘时触发
        private void Window_KeyDown(object sender, KeyEventArgs e)
        {
            // 获取当前的 ViewModel
            var viewModel = DataContext as MainWindowViewModel;

            // 如果 ViewModel 为空,则直接返回,不进行任何操作
            if (viewModel == null)
                return;

            // 根据按下的键执行相应的操作

            // 检查是否按下了数字键 0-9,并且没有按下 Shift 键
            if (e.Key >= Key.D0 && e.Key <= Key.D9 && e.KeyModifiers.HasFlag(KeyModifiers.Shift) == false)
            {
                // 将数字转换为字符串并传递给命令
                string digit = (e.Key - Key.D0).ToString();
                viewModel.AddDigitOrOperationCommand.Execute(digit);
            }
            // 检查是否按下了加号键(+),支持数字键盘的加号以及 Shift + OemPlus(通常是 + 键)
            else if (e.Key == Key.Add || (e.Key == Key.OemPlus && e.KeyModifiers.HasFlag(KeyModifiers.Shift)))
            {
                viewModel.AddDigitOrOperationCommand.Execute("+");
            }
            // 检查是否按下了减号键(-)
            else if (e.Key == Key.Subtract)
            {
                viewModel.AddDigitOrOperationCommand.Execute("-");
            }
            // 检查是否按下了乘号键(*),支持数字键盘的乘号以及 Shift + 8(通常是 * 键)
            else if (e.Key == Key.Multiply || (e.Key == Key.D8 && e.KeyModifiers.HasFlag(KeyModifiers.Shift)))
            {
                viewModel.AddDigitOrOperationCommand.Execute("*");
            }
            // 检查是否按下了除号键(/),支持数字键盘的除号以及 Oem2(通常是 / 键)
            else if (e.Key == Key.Divide || e.Key == Key.Oem2)
            {
                viewModel.AddDigitOrOperationCommand.Execute("/");
            }
            // 检查是否按下了等于号键(=)或回车键(Enter)
            else if (e.Key == Key.OemPlus || e.Key == Key.Enter)
            {
                viewModel.AddDigitOrOperationCommand.Execute("=");
            }
            // 检查是否按下了删除键(Backspace)或删除键(Delete)
            else if (e.Key == Key.Back || e.Key == Key.Delete)
            {
                viewModel.ClearCommand.Execute(null);  // 执行清除命令
            }
        }
    }
}

 MainWindow.axaml.cs代码

using Avalonia.Input;
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;

namespace CalculatorApp
{
    public class MainWindowViewModel : INotifyPropertyChanged
    {
        // 私有字段,用于存储显示的文本、当前操作符、结果和其他操作状态
        private string _displayText = "0";  // 显示屏的默认值为 "0"
        private string _displaySymbol = "";  // 用于显示当前的运算符号
        private string _displayResult = "";  // 显示最终的运算结果
        private string _currentOperation;  // 当前正在进行的操作符
        private double _firstNumber;  // 存储第一个操作数
        private bool _isOperationPending;  // 标志是否有未完成的操作
        private bool _isNewEntry = true;  // 标志是否是新的输入
        private bool _isResultDisplayed = false;  // 标志是否刚刚显示了计算结果
        private string _displayAll;  // 用于显示所有操作记录

        // 实现 INotifyPropertyChanged 接口,用于通知 UI 属性的变化
        public event PropertyChangedEventHandler PropertyChanged;

        public MainWindowViewModel()
        {
            // 初始化命令,将按钮绑定到相应的命令
            AddDigitOrOperationCommand = new RelayCommand<string>(AddDigitOrOperation);  // 处理数字和操作符的输入
            ClearCommand = new RelayCommand(Clear);  // 处理清除操作
            EqualsCommand = new RelayCommand(Calculate);  // 处理等于操作
        }

        // 公有属性,用于绑定 UI
        public string DisplayAll
        {
            get => _displayAll;
            set
            {
                _displayAll = value;
                OnPropertyChanged(nameof(DisplayAll));  // 通知 UI 属性已更改
            }
        }

        public string DisplayText
        {
            get => _displayText;
            set
            {
                _displayText = value;
                OnPropertyChanged();  // 使用 CallerMemberName 自动获取属性名称
            }
        }

        public string DisplaySymbol
        {
            get => _displaySymbol;
            set
            {
                _displaySymbol = value;
                OnPropertyChanged();
            }
        }

        public string DisplayResult
        {
            get => _displayResult;
            set
            {
                _displayResult = value;
                OnPropertyChanged();
            }
        }

        // 命令用于处理各种用户操作
        public ICommand AddDigitOrOperationCommand { get; }  // 处理数字或操作符
        public ICommand ClearCommand { get; }  // 清除输入和结果
        public ICommand EqualsCommand { get; }  // 执行等于运算
        public ICommand NegateCommand { get; }  // 处理取反操作(可扩展)
        public ICommand PercentCommand { get; }  // 处理百分比操作(可扩展)

        // 根据输入值判断是数字还是操作符
        private void AddDigitOrOperation(string input)
        {
            if (IsOperation(input))
            {
                SetOperation(input);  // 如果是操作符,则调用 SetOperation
            }
            else
            {
                AddDigit(input);  // 如果是数字,则调用 AddDigit
            }
        }

        // 判断输入是否是操作符
        private bool IsOperation(string input)
        {
            return input == "+" || input == "-" || input == "*" || input == "/" || input == "=";
        }

        // 添加数字到显示屏
        private void AddDigit(string digit)
        {
            // 如果刚刚显示过结果,清空显示
            if (_isResultDisplayed)
            {
                DisplayAll = "";
                DisplayResult = "";
                _isResultDisplayed = false;
            }

            // 如果是新输入,则替换显示内容,否则追加
            if (_isNewEntry)
            {
                DisplayText = digit == "." ? "0." : digit;
                _isNewEntry = false;
                DisplayAll += digit;
            }
            else
            {
                // 避免重复输入小数点
                if (digit == "." && DisplayText.Contains("."))
                    return;

                DisplayText += digit;
                DisplayAll += digit;
            }
        }

        // 设置操作符并处理运算
        private void SetOperation(string operation)
        {
            if (!_isOperationPending)  // 如果当前没有进行中的操作
            {
                _firstNumber = double.Parse(DisplayText);  // 解析输入的第一个数字
                _currentOperation = operation;  // 保存当前操作符
                _isOperationPending = true;  // 标记操作进行中
                _isNewEntry = true;  // 准备接受新的输入

                // 显示操作符
                switch (operation)
                {
                    case "+":
                    case "-":
                    case "*":
                    case "/":
                        DisplaySymbol = operation;
                        break;
                    case "=":
                        Calculate();  // 如果操作符是 "=", 则执行计算
                        return;
                }
                DisplayAll += DisplaySymbol;
            }
            else
            {
                // 如果有进行中的操作,执行计算后再设置新的操作符
                Calculate();
                _currentOperation = operation;
            }
        }

        // 执行计算逻辑
        private void Calculate()
        {
            if (!_isOperationPending)
                return;

            double secondNumber = double.Parse(DisplayText);  // 获取输入的第二个数字
            double result = 0;

            try
            {
                // 根据操作符计算结果
                switch (_currentOperation)
                {
                    case "+":
                        result = _firstNumber + secondNumber;
                        break;
                    case "-":
                        result = _firstNumber - secondNumber;
                        break;
                    case "*":
                        result = _firstNumber * secondNumber;
                        break;
                    case "/":
                        if (secondNumber == 0)
                            throw new DivideByZeroException();
                        result = _firstNumber / secondNumber;
                        break;
                }

                // 更新显示结果
                DisplayAll += "=";
                DisplayResult = result.ToString();
                _firstNumber = result;  // 将结果作为下一次操作的第一个数字
                _isNewEntry = true;
                _isOperationPending = false;
                _isResultDisplayed = true;  // 标记刚刚显示了结果
            }
            catch (Exception)
            {
                DisplayText = "Error";  // 捕获错误,例如除零错误
                _isNewEntry = true;
                _isOperationPending = false;
                DisplaySymbol = "";
            }
        }

        // 清除输入和结果
        private void Clear()
        {
            DisplayText = "0";  // 重置显示屏
            DisplaySymbol = "";  // 清除操作符
            DisplayAll = "";  // 清空所有显示
            DisplayResult = "";  // 清空结果
            _firstNumber = 0;  // 重置第一个数字
            _currentOperation = null;  // 清除当前操作符
            _isOperationPending = false;  // 重置操作状态
            _isNewEntry = true;  // 重置为新输入状态
            _isResultDisplayed = false;  // 重置结果显示状态
        }

        // 通知属性已更改,刷新 UI
        protected void OnPropertyChanged([CallerMemberName] string name = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
    }

    // RelayCommand 类:用于绑定命令和操作
    public class RelayCommand<T> : ICommand
    {
        private readonly Action<T> _execute;  // 执行操作的委托
        private readonly Func<T, bool> _canExecute;  // 判断操作是否可以执行的委托

        public RelayCommand(Action<T> execute, Func<T, bool> canExecute = null)
        {
            _execute = execute;
            _canExecute = canExecute;
        }

        // 判断命令是否可以执行
        public bool CanExecute(object parameter) => _canExecute == null || _canExecute((T)parameter);

        // 执行命令
        public void Execute(object parameter) => _execute((T)parameter);

        // 事件,当命令的可执行状态发生变化时触发
        public event EventHandler CanExecuteChanged
        {
            add { }
            remove { }
        }
    }

    // 不带参数的 RelayCommand 类,用于绑定简单操作
    public class RelayCommand : ICommand
    {
        private readonly Action _execute;
        private readonly Func<bool> _canExecute;

        public RelayCommand(Action execute, Func<bool> canExecute = null)
        {
            _execute = execute;
            _canExecute = canExecute;
        }

        // 判断命令是否可以执行
        public bool CanExecute(object parameter) => _canExecute == null || _canExecute();

        // 执行命令
        public void Execute(object parameter) => _execute();

        // 事件,当命令的可执行状态发生变化时触发
        public event EventHandler CanExecuteChanged
        {
            add { }
            remove { }
        }
    }
}

另外就是发布成各种平台的方法了:

右击工程点击发布-》选择文件夹,相当于支持了win,linux,osx,以及x86,x64,arm多种架构。

下载代码如下:

AvaloniaCalculatorApp: 一个基于Avalonia架构的c#简单的计算器应用,支持windows ,linux(ubuntu,kylin,uos),visual 2022开发 (gitee.com)icon-default.png?t=N7T8https://gitee.com/sunyuzhe114/AvaloniaCalculatorApp

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

贪心-单调递增的数字

给定一个非负整数 N&#xff0c;找出小于或等于 N 的最大的整数&#xff0c;同时这个整数需要满足其各个位数上的数字是单调递增。 &#xff08;当且仅当每个相邻位数上的数字 x 和 y 满足 x < y 时&#xff0c;我们称这个整数是单调递增的。&#xff09; 示例 1: 输入: …

如何显示Dialog窗口

文章目录 1. 概念介绍2. 使用方法2.1 Overlay效果2.1 Dialog效果 3. 示例代码4. 内容总结 我们在上一章回中介绍了"使用get显示snackBar"相关的内容&#xff0c;本章回中将介绍使用get显示Dialog.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在…

又一款强大好用的Shell脚本项目,支持Bash,Sh、Dash、Ksh等,甚至可以在编辑器中直接用,程序员必备!(附源码)

作为一个程序员&#xff0c;肯定经常都要和shell脚本打交道&#xff0c;Shell脚本可以帮我们自动化各种任务&#xff0c;但也经常有格式错误、拼写错误、逻辑错误等等麻烦&#xff0c;而且它不会告诉你错在哪里&#xff01; 今天就给大家分享一个超级实用的开源项目 - ShellCh…

Vue接入高德地图并实现基本的路线规划功能

目录 一、申请密钥 二、安装依赖 三、代码实现 四、运行截图 五、官方文档 一、申请密钥 登录高德开放平台&#xff0c;点击我的应用&#xff0c;先添加新应用&#xff0c;然后再添加Key。 如图所示填写对应的信息&#xff0c;系统就会自动生成。 二、安装依赖 npm i am…

Opencv中的直方图(3)直方图比较函数compareHist()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 比较两个直方图。 函数 cv::compareHist 使用指定的方法比较两个密集或两个稀疏直方图。 该函数返回 d ( H 1 , H 2 ) d(H_1, H_2) d(H1​,H2​…

el-form之表单校验自动定位到报错位置问题,,提升用户体验

需求描述 由于需要填写的表单项太多&#xff0c;提交的时候校验不通过&#xff0c;如果没填写的表单项在最上面&#xff0c;用户看不到不知道发生了啥&#xff0c;所以需要将页面滚动定位到第一个报错的表单项位置&#xff0c;提升用户体验 实现步骤 点击保存校验 报错项class会…

echarts 水平柱图 科技风

var category [{ name: "管控", value: 2500 }, { name: "集中式", value: 8000 }, { name: "纳管", value: 3000 }, { name: "纳管", value: 3000 }, { name: "纳管", value: 3000 } ]; // 类别 var total 10000; // 数据…

基于BiLSTM-CRF的医学命名实体识别研究(下)模型构建

一.生成映射字典 接下来需要将每个汉字、边界、拼音、偏旁部首等映射成向量。所以&#xff0c;我们首先需要来构造字典&#xff0c;统计多少个不同的字、边界、拼音、偏旁部首等&#xff0c;然后再构建模型将不同的汉字、拼音等映射成不同的向量。 在prepare_data.py中自定义…

Vue 获取参数

Vue 获取参数 在Vue.js开发过程中&#xff0c;获取参数是处理用户输入和动态数据的关键环节。本文将深度解析Vue中获取参数的几种方法&#xff0c;并分享一些扩展与高级技巧&#xff0c;帮助你更高效地完成参数处理任务。 文章目录 Vue 获取参数 一、Vue获取参数包含哪些几种1.…

【无标题】nginx服务器代码信息、数据库连接信息、敏感文件的路径、服务器版本信息发起有针对性的攻击

Nginx敏感文件的路径、服务器版本信息 Nginx 403、404、500等错误时&#xff0c;返回详细错误信息。报错信息中可能会包含服务器代码信息、数据库连接信息、敏感文件的路径、服务器版本信息等&#xff0c;攻击者可以利用这些信息来寻找已知的漏洞&#xff0c;从而发起有针对性…

mybatis 查询Not Found TableInfoCache

近期在工程迁移中遇到一个mybatis查询的问题&#xff0c;检查代码没有问题&#xff0c;但是报Not Found TableInfoCache 解决过程 是不是数据库对应表错误或者实体类指定的表名错误 查看配置文件链接的数据源是否正确TableName中指定的表名然后去数据库看一下是否存在 如果…

spring揭秘19-spring事务01-事务抽象

文章目录 【README】【1】事务基本元素【1.1】事务分类 【2】java事务管理【2.1】基于java的局部事务管理【2.2】基于java的分布式事务管理【2.2.1】基于JTA的分布式事务管理【2.2.2】基于JCA的分布式事务管理 【2.3】java事务管理的问题 【3】spring事务抽象概述【3.1】spring…

MSSQL数据库安全配置

预备知识 1、数据库安全的概念 对任何企业组织来说,数据的安全性最为重要。安全性主要是指允许那些具有相应的数据访问权限的用户能够登录到数据库,并访问数据以及对数据库对象实施各种权限范围内的操作,但是要拒绝所有的非授权用户的非法操作。因此安全性管理与用户管理是…

pptpd配置文件/etc/pptpd.conf详解

正文共&#xff1a;1111 字 2 图&#xff0c;预估阅读时间&#xff1a;1 分钟 如果要在Linux系统配置PPTP&#xff08;Point-to-Point Tunneling Protocol&#xff0c;点到点隧道协议&#xff09;VPN&#xff0c;一般是使用pptpd软件。pptpd命令通常从配置文件/etc/pptpd.conf中…

6.第二阶段x86游戏实战2-理解程序流程

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 工具下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1rEEJnt85npn7N38Ai0_F2Q?pwd6tw3 提…

CNSS Recruit 2024 Web方向 题解WriteUp

文章首发于【先知社区】&#xff1a;https://xz.aliyun.com/t/15586 babyHTTP 开题&#xff0c;Http传参问题 GET&#xff1a; ?CNSShackersPOST&#xff1a; webfunCookie&#xff1a; admintruePHPinfo 开题 根据题目描述&#xff0c;猜测phpinfo.php文件有东西。 phpinfo…

什么是嵌入式?行业前景如何?

目录 什么是嵌入式&#xff1f; 主要特点 常见应用场景 1. 工业自动化 2. 交通运输 3. 智能家居 4. 消费电子 5. 医疗设备 6. 航空航天 7. 物联网&#xff08;IoT&#xff09; 8. 能源管理 行业前景如何&#xff1f; 市场需求强劲 物联网&#xff08;IoT&#xff09;的爆发 汽车…

AutoDroid: LLM-powered Task Automation inAndroid论文学习

光看题目怎么和上一篇差不多&#xff1f;又是纯用LLM的&#xff1f; 当然还是有一点不一样的&#xff1a; 这里的最大特点是加上了UI领域知识&#xff0c;可以大幅增强LLM在处理UI方面的知识的能力。根据文章的说法&#xff0c;使用了这招他们的LLM可以吊打GPT4V&#xff0c;准…

优秀的安防视频监控平台应该具备怎样的视频编解码能力?

随着安防技术的飞速发展&#xff0c;监控平台作为保障公共安全、维护社会秩序的重要工具&#xff0c;其性能与效率日益成为行业关注的焦点。其中&#xff0c;监控平台的视频编码能力在视频监控系统中扮演着至关重要的角色&#xff0c;视频编码技术作为监控系统的核心组成部分&a…

记一次导入dbf文件后数据为空问题的解决方法

前言 省流&#xff1a;这篇文章最终采用的是更换导出文件格式的方法&#xff0c;看到这里觉得方法不适用的小伙伴可以不用浪费几秒钟看完这篇文章哦。 问题描述 作者使用的是Navicat数据库管理工具&#xff0c;然后在将源数据库的数据表导出为dbf格式文件后&#xff0c;再将…