WPF【09】WPF基础入门 (三层架构与MVC架构)

news2025/6/3 21:36:20

9-2 【操作】WPF 基础入门
新建一项目
Create a new project - WPF Application (A project for creating a .NET Core WPF Application) - Next - .NET 5.0 (Current) - Create

项目创建完成,VS自动打开 GUI用户界面,格式是 .xaml文件,跟xml差不多,也属于xml文件的类别。
虽然xaml是WPF用户的底层标准,但是VS已帮我们全部封装好了,可以直接拖拽布局界面。

9-3 【理论】XAML页面剖析
MainWindow.xaml代码示例
<Window x:Class="WpfApp.MainWindow"
        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:WpfApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Button Height="50" Width="100" Content="CLick me 4" />
        <d:Button>
            <Button.Height>50</Button.Height>
            <Button.Width>100</Button.Width>
            <Button.Content>
                <TextBlock>Click me 4</TextBlock>
            </Button.Content>
        </d:Button>
    </Grid>
</Window>

上面标红的<Button> 相当于下面的7行代码(当然不能有 d:),因为<Button ……> 的内部属性可以通过“元素嵌套”的方式声明。

<Window ……> 根元素介绍
xmlns 是 xml-namespace 的缩写,用于定义命名空间的。上面看到的是MS系统默认的命名空间,可以使用这个命名空间下的所有UI控件。
    比如这里的 Button TextBlock,另外当来源不同的类重名时,也可以通过命名空间区分不同的UI控件。
xmlns 是默认的命名空间,这种不带任何映射参数的命名空间,整个页面只能有一个,一般使用元素最频繁使用的命名空间。
    比如这里的 Window Grid Button TextBlock,都来自 xmlns 。

接着,还能看到带有映射前缀的:x 、:d 等的命名空间,这些命名空间都与解析 xaml语言相关,
    比如这里的 x:Class 来自 xmlns:x 这个命名空间,它将会指定当前页面所对应的 cs 文件,以及当前页面所对应的类的名称。
    比如这里的 xmlns:local代表当前应用的命名空间,即项目名称:WpfApp,而 
    Title="MainWindow" Height="450" Width="800" 分别定义了视窗的标题、高度和宽度。

mc:Ignorable="d"这个命名空间稍微有点费解,它的名称叫 Ignorable,即可以忽略的,表示在运行过程中可以被忽略的控件,而这些可忽略的控件使用 d: 来引导。即运行时忽略,上面布局中有两个 Button ,运行时,下面的Button不会显示的。


MainWindow.xaml.cs(UI页面逻辑代码)代码示例
……
namespace WpfApp
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            var grid = (Grid)this.Content;
            Button button = new Button();
            button.Height = 50;
            button.Width = 100;
            Margin = new Thickness(0, 0, 700, 385);
            button.Content = "Button !!!";

            grid.Children.Add(button);
        }
    }
}

x:Class="WpfApp.MainWindow" 对应上面的 namespace WpfApp 和 class MainWindow。
构造函数 public MainWindow() 在程序启动时调用。InitializeComponent();帮助完成页面初始化工作(比如初始化标题、字体大小等)。

<Grid>就是页面的内容,cs中 this.Content 访问的<Grid>元素,cs中 var grid = (Grid)this.Content; 下面就是用 代码的方式添加Button按钮。
纯粹使用 cs 来完成用户界面的做法已经非常过时了,主流的界面开发工作更加倾向于MVC(Model View Controller),即:数据模型-视图-控制逻辑 三者分离的模式。
建议使用 xaml 来进行页面设计,而通过 cs 来控制页面和数据的动态变化。

9-4 【拓展】MVC 架构
什么是MVC
  ·软件工程的架构方式
  ·模型(Model)、视图(View)和控制器(Controller)
  ·分离业务操作、数据显示、逻辑控制

从而使用同一个程序可以使用不同的表现形式!

请问:Model就是用来访问数据库的吗?

对于整个MVC架构,最难理解的就是Model模型了。
很多程序员在最开始使用MVC框架时,都会误认为Model就是用来访问数据库索取数据的,而最重要的业务逻辑却放在控制器(Controller)里,最终写出来的系统结构,就变成了:View用来显示界面、Controller做核心业务、Model仅仅用来访问数据库,做数据变化而已。很明显,这是混淆了另一种软件开发模式:三层架构。

三层架构 和 MVC 有些类似,也是分为三个部分。

三层架构
  ·UI层,表示用户界面
  ·BLL(Business Logic Layer)业务逻辑层,处理核心业务以及数据封装
  ·DAL(Data Access Layer)层,表示数据访问

这种三层架构曾经红极一时,不过现在逐渐被 MVC、DDD(领域驱动)、Microservices(微服务)等架构取代了。

简单来说,MVC 与 三层架构 除了都分为三个部分以外,也没什么共同点了!

MVC 与 三层架构
  ·三层架构面向接口编程,而三个层级之间的完全解耦、完全可替换
  ·MVC的每个部分都是紧密结合的,它的核心并不是解耦,而是重用


也就是说,MVC中同样的Model可以适配于不同的控制器,搭配不同的视图用来显示不同的内容,然而系统最核心的逻辑始终包含在模型(Model)中,可以被重复使用。
三层架构所描述的是自下而上,具有明显层级的架构。首先,得有数据库,根据数据库来创建DAL(Data Access Layer) 来获取和映射数据;得到原始数据后传递给BLL(Business Logic Layer)业务逻辑层,进行数据验证、数据转换、对象封装;最后封装好的数据传递给UI层,显示给用户。

MVC架构各个组成部分是水平架构的,只有调用关系,没有层级关系。所有的数据流动和显示,都是通过数据绑定事件驱动所处理的。
首先,应该确定核心业务模型(Model),通过Model来创建数据库;
第二,用户发起请求,将请求传递给控制器;
第三,控制器调用模型;
第四,模型获取数据,对数据做出验证,并将转换好的数据交还给Controller,业务逻辑也发生在这里;
第五,Controller把数据交给视图,视图向用户展示数据。

所以,MVC架构中一定要知道自己的核心业务是什么,所有业务都要围绕它展开,不要混淆三层架构设计理念。

为什么要使用MVC呢?因为有各种好处:

MVC的优点
第一、耦合性低
    视图层和业务层可以分离,这样就允许修改视图层代码,而不需要重新编译模型和控制器的代码;比如,改写 jsp、html、css 或者 js 代码,并不需要重启服务器。同样,一个业务流程或业务规则发生改变,只需要改变MVC的模型,因为模型与控制器、视图相分离,所以很容易改变应用程序的数据层 和 业务规则。
第二、可复用性高
    MVC的各种组件都具有高可复用性,随着技术的不断进步需要越来越多的方式来访问应用程序,MVC模式允许各种各样不同样式的视图来访问同一个服务端的代码,多个视图可以共享一个模型。
    比如用户可以通过 Web应用,也可以通过手机App来订购某样产品,虽然订购的方式不一样,但处理订购产品的业务是一样的,由于模型访问数据并没有发生改变,所以同样的功能可以被不同的界面使用。
第三、高可维护性
    MVC也具有高可维护性,分离视图和业务逻辑,可以使得Web应用更容易维护和修改,比如,如果想更改业务逻辑,只需要更改业务逻辑,……,这样的好处就是后期维护成本降低,新功能的增加、代码的扩展也非常方便。


MVC的缺点
第一、定义不明确,学习曲线陡
    大家都是依照自己经验来解释和使用MVC,而MVC内部原理比较复杂,组合多种设计模式,所以完全理解MVC并不是很容易,需要花一些时间去思考,尤其对新手来说,有一定的学习曲线
第二、结构复杂
    MVC并不适合小型,甚至中等规模的应用程序,对于简单的页面,严格遵循MVC,反而会增加结构的复杂性,可能产生过多的数据操作,导致运行效率低下
第三、数据流动效率低
    依据模型操作接口的不同,视图可能需要多次调用才能获得足够的数据显示,对于未变化的数据频繁地访问模型,也可能会造成操作性能的下降,所以从数据操作角度来说,过多地频繁访问会导致数据流动的效率下降。


9-5 【理论】逻辑树与视觉树

StackPanel 是纵向排列的空间,可以在里面添加各种各样的控件。

<StackPanel>
    <TextBlock HorizontalAlignment="Center" Margin="20">Hello World</TextBlock>
    <ListBox Height="100" Width="100">
        <ListBoxItem Content="item 1"></ListBoxItem>
        <ListBoxItem Content="item 2"></ListBoxItem>
        <ListBoxItem Content="item 3"></ListBoxItem>
        <ListBoxItem Content="item 4"></ListBoxItem>
    </ListBox>
    <Button Margin="20" Width="100" Click="Button_Click">随便</Button>
</StackPanel>

cs中代码
private void Button_Click(object sender, RoutedEventArgs e)
{
    MessageBox.Show("按钮被点击了!"); //这里加入断点
}

给上面点击事件,加入断点。启动调试,在“Autos”中,找到“Name”中 sender 对应的“Value”中,鼠标放到放大镜上,提示“WPF Tree Visualizer”,点击【放大镜】进入视觉树查看页面。
在这个窗口中,左边是视觉树,右边是当前视觉树(选中的)节点所有的属性。

从页面来说整个像是一棵树被倒过来一样。从树根出发,一层一层开枝散叶,树根 MainWindow ,而 MainWindow 连接的是视觉节点 Border(边框),继续连接后续的视觉节点等等。
不过,在视觉树中,也可以找到逻辑节点。比如 StackPanel、TextBlock、ListBox 等等。

从原理来说,逻辑树是视觉树的子集

逻辑树是视觉树的子集示例图

9-6 【操作】Grid 网格系统

Grid网格是WPF中最基本的行列布局工具。
示例:3行3列的网格布局
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="3*"></ColumnDefinition>
        <ColumnDefinition Width="2*"></ColumnDefinition>
        <ColumnDefinition Width="*"></ColumnDefinition>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"></RowDefinition>
        <RowDefinition Height="*"></RowDefinition>
        <RowDefinition Height="*"></RowDefinition>
    </Grid.RowDefinitions>
    <Button Grid.Row="0" Grid.Column="0">click me dddd </Button>
    <Button Grid.Row="0" Grid.Column="1">click me 2</Button>
    <Button Grid.Row="1" Grid.Column="0">click me 3</Button>
    <Button Grid.Row="1" Grid.Column="1">click me 2</Button>
    <TextBlock Grid.Row="2" Grid.Column="0">Hello World</TextBlock>
</Grid>

Width值中:* 是权重操作,值还可以是 auto,或 数字(表示像素) 等

9-7 【操作】依赖属性与数据处理

<Grid>
<Button Height="100" Width="200" Content="ClickMe">
<Button.Style>
    <Style TargetType="Button">
        <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="FontSize" Value="25"></Setter>
            <Setter Property="Foreground" Value="White"></Setter>
        </Trigger>
        </Style.Triggers>
    </Style>
</Button.Style>
</Button>
</Grid>

在xaml中到处都是属性,像这边Button中的属性Height等,所有这些属性都依赖于 Button.Style 中所定义的 property,也就是说,这些UI上的属性 与 事件触发属性是绑定在一起的,从数据流动的角度来说,这就是数据绑定最基本的逻辑。属性依赖也可以让相关的UI控件知道,当前事件的处理逻辑

public class Button : ButtonBase {
    public static readonly DependencyProperty IsCancelProperty;
    public static readonly DependencyProperty IsDefaultedProperty;
    public static readonly DependencyProperty IsDefaultProperty;
    public Button();
    public bool IsCancel{ get; set; }
    public bool IsDefault { get; set; }
    public bool IsDefaulted { get; }
    ……
}

这里可以看到3个readonly的DependencyProperty,也就是属性依赖,分别用来判断默认属性、属性取消、以及是否回到默认属性。同时对应这三个依赖属性,还有3个基础属性,在程序正常运行时,这3个基础属性会与依赖属性互相连接,而这3组属性则可以控制UI控件中的动态变化。比如,样式数据的绑定、动画效果,甚至样式的继承。

而在这个 ButtonBase 中,继承于ContentControl,在它内部除了有可以处理事件的 RoutedEvent 以外,所有其他的都是依赖属性。
public abstract class ButtonBase : ContentControl, ICommandSource {
    public static readonly RoutedEvent ClickEvent;
    public static readonly DependencyProperty ClickModeProperty;
    public static readonly DependencyProperty CommandParameterProperty;
    public static readonly DependencyProperty CommandProperty;
    public static readonly DependencyProperty CommandTargetProperty;
    public static readonly DependencyProperty IsPressedProperty;
    ……
}
public class ContentControl : Control, IAddChild {
    ……
}

让我们更深入一点,进入ContentControl,再进入 Control,同样可以看到类似的属性依赖,可以看到刚刚使用过的 FontSizeProperty 字体大小、ForegroundProperty 前景,等各种各样其他的属性,对于WPF的UI控件来说,属性依赖是最基础的数据和最基础的事件传递机制。

public class Control : FrameworkElement {
    public static readonly DependencyProperty BackgroundProperty;
    public static readonly DependencyProperty TemplateProperty;
    public static readonly DependencyProperty TabIndexProperty;
    public static readonly RoutedEvent PreviewMouseDoubleClickEvent;
    public static readonly DependencyProperty PaddingProperty;
    public static readonly RoutedEvent MouseDoubleClickEvent;
    public static readonly DependencyProperty IsTabStopProperty;
    …………
    public static readonly DependencyProperty FontSizeProperty;
    …………
    public static readonly DependencyProperty ForegroundProperty;
}


9-8 【操作】Data Binding 数据绑定

1. 单向绑定 one way bining : Source -> Target
2. 双向绑定 two way bining : Source <-> Target
3. 指定方向单向绑定 oneWayToSource Target -> Source
4. 单次绑定 One Time -> 构造方法中单次执行

<StackPanel>
    <TextBox Name="myTextBox" Width="100" Margin="50" Text="{Binding ElementName=mySlider, Path=Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
    <Slider Name="mySlider" Minimum="0" Maximum="100" IsSnapToTickEnabled="True"></Slider>
</StackPanel>

指定绑定的数据内容是什么?指定数据需要使用 Path 属性,这里的 Path 其实是 Slider 的数据,也就是 Value,最后指定绑定方式。
IsSnapToTickEnabled="True" 则显示的数字,拖动不会显示小数了。

有什么办法,不需要按下 Tab键,就进行数据绑定呢?
有,加上 UpdateSourceTrigger=PropertyChanged 

One Time绑定,就是一次性的绑定。
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        mySlider.Value = 35;
        myTextBox.Text = mySlider.Value.ToString();
    }
}

9-9 【操作】INotifyPropertyChanged 事件处理

<StackPanel>
    <Label Content="number 1"></Label>
    <TextBox Width="200" Margin="30" Text="{Binding Path=Num1, Mode=TwoWay}"></TextBox>
    <Label Content="number 2"></Label>
    <TextBox Width="200" Margin="30" Text="{Binding Path=Num2, Mode=TwoWay}"></TextBox>
    <Label Content="Resule"></Label>
    <TextBox Width="200" Margin="30" Text="{Binding Path=Result, Mode=TwoWay}"></TextBox>
</StackPanel>

cs中代码:
public partial class MainWindow : Window
{
    public Sum Sum { get; set; }

    public MainWindow()
    {
        InitializeComponent();
        Sum = new Sum() { Num1 = "1", Num2 = "2" };
        this.DataContext = Sum;
    }
}

新建一个Sum.cs类文件。Sum实现INotifyPropertyChanged接口(在 System.ComponentModel 命名空间下),让VS自动实现接口:public event PropertyChangedEventHandler PropertyChanged;
这样就多了一个方法 PropertyChangedEventHandler,它是一个典型的事件处理委托。
接着来添加事件的触发处理 OnPropertyChanged 方法,因为 TextBox的输入都是字符串,所以监听数据是 string property。

为了能够处理这三个TextBox的联动,还需要在 Num1和Num2 的Set中发送 OnPropertyChanged("Result"); 计算Result这个事件。


public class Sum : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string property)
    {
        if (PropertyChanged == null) //防御性编程
        {
            return;
        }
        PropertyChanged(this, new PropertyChangedEventArgs(property)); //事件处理机制
    }

    private string _num1;
    private string _num2;
    private string _result;

    public string Num1
    {
        get
        {
            return _num1;
        }
        set
        {
            int number;
            bool result = int.TryParse(value, out number);
            if(result)
            {
                _num1 = value;
                OnPropertyChanged("Num1");
                OnPropertyChanged("Result");
            }
        }
    }

    public string Num2
    {
        get
        {
            return _num2;
        }
        set
        {
            int number;
            bool result = int.TryParse(value, out number);
            if (result)
            {
                _num2 = value;
                OnPropertyChanged("Num2");
                OnPropertyChanged("Result");
            }
        }
    }

    public string Result
    {
        get
        {
            int result = int.Parse(_num1) + int.Parse(_num2);
            return result.ToString();
        }
        set
        {
            int result = int.Parse(_num1) + int.Parse(_num2);
            _result = result.ToString();
            OnPropertyChanged("Result");
        }
    }
}


 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

macOS 风格番茄计时器:设计与实现详解

macOS 风格番茄计时器&#xff1a;设计与实现详解 概述 本文介绍一款采用 macOS 设计语言的网页版番茄计时器实现。该计时器完全遵循苹果的人机界面指南(HIG)&#xff0c;提供原汁原味的 macOS 使用体验&#xff0c;同时具备响应式设计和深色模式支持。 核心特性 原生 macOS…

oracle goldengate实现远程抽取postgresql 到 postgresql的实时同步【绝对无坑版,亲测流程验证】

oracle goldengate实现postgresql 到 postgresql的实时同步 源端&#xff1a;postgresql1 -> postgresql2 流复制主备同步 目标端&#xff1a;postgresql 数据库版本&#xff1a;postgresql 12.14 ogg版本&#xff1a;21.3 架构图&#xff1a; 数据库安装以及流复制主备…

ISCC-2025-web-wp

web 校赛 校赛靠着ENOCH师傅发力&#xff0c;也是一路躺进了区域赛&#xff0c;E师傅不好意思发这抽象比赛的wp(这比赛确实啥必到让人大开眼界&#xff0c;反正明年我是肯定不会打了)&#xff0c;我就顺手要过来连着区域赛的一起发了 web 150分 按照提示进入/includes/fla…

King3399(ubuntu文件系统)iic(i2c)功能测试

0 引言 前面两篇博文简要介绍了板子上uart部分的内容&#xff0c;但在驱动开发时&#xff0c;我们遇到的外设更多的是以i2c或spi进行通信&#xff0c;本文将对king3399的i2c进行测试并对硬件电路、设备树与驱动程序进行分析 如果使用的i2c设备不是mma8452&#xff0c;建议先看…

德思特新闻 | 德思特与es:saar正式建立合作伙伴关系

德思特新闻 2025年5月9日&#xff0c;德思特科技有限公司&#xff08;以下简称“德思特”&#xff09;与德国嵌入式系统专家es:saar GmbH正式达成合作伙伴关系。此次合作旨在将 es:saar 的先进嵌入式开发与测试工具引入中国及亚太市场&#xff0c;助力本地客户提升产品开发效率…

基于原生JavaScript前端和 Flask 后端的Todo 应用

Demo地址&#xff1a;https://gitcode.com/rmbnetlife/todo-app-js-flask.git Python Todo 应用 这是一个使用Python Flask框架开发的简单待办事项(Todo)应用&#xff0c;采用前后端分离架构。本项目实现了待办事项的添加、删除、状态切换等基本功能&#xff0c;并提供了直观…

MIT 6.S081 2020 Lab6 Copy-on-Write Fork for xv6 个人全流程

文章目录 零、写在前面一、Implement copy-on write1.1 说明1.2 实现1.2.1 延迟复制与释放1.2.2 写时复制 零、写在前面 可以阅读下 《xv6 book》 的第五章中断和设备驱动。 问题 在 xv6 中&#xff0c;fork() 系统调用会将父进程的整个用户空间内存复制到子进程中。**如果父…

第304个Vulnhub靶场演练攻略:digital world.local:FALL

digital world.local&#xff1a;FALL Vulnhub 演练 FALL (digitalworld.local: FALL) 是 Donavan 为 Vulnhub 打造的一款中型机器。这款实验室非常适合经验丰富的 CTF 玩家&#xff0c;他们希望在这类环境中检验自己的技能。那么&#xff0c;让我们开始吧&#xff0c;看看如何…

Unity 模拟高度尺系统开发详解——实现拖动、范围限制、碰撞吸附与本地坐标轴选择

内容将会持续更新&#xff0c;有错误的地方欢迎指正&#xff0c;谢谢! Unity 模拟高度尺系统开发详解——实现拖动、范围限制、碰撞吸附与本地坐标轴选择 TechX 坚持将创新的科技带给世界&#xff01; 拥有更好的学习体验 —— 不断努力&#xff0c;不断进步&#xff0c;不…

万字详解RTR RTSP SDP RTCP

目录 1 RTSP1.1 RTSP基本简介1.2 RSTP架构1.3 重点内容分析 2 RTR2.1 RTR简介2.2 RTP 封装 H.2642.3 RTP 解封装 H.2642.4 RTP封装 AAC2.5 RTP解封装AAC 3 SDP3.1 基础概念3.2 SDP协议示例解析3.3 重点知识 4 RTCP4.1 RTCP基础概念4.2 重点 5 总结 1 RTSP 1.1 RTSP基本简介 一…

云服务器如何自动更新系统并保持安全?

云服务器自动更新系统是保障安全、修补漏洞的重要措施。下面是常见 Linux 系统&#xff08;如 Ubuntu、Debian、CentOS&#xff09;和 Windows 服务器自动更新的做法和建议&#xff1a; 1. Linux 云服务器自动更新及安全维护 Ubuntu / Debian 系统 手动更新命令 sudo apt up…

[paddle]paddle2onnx无法转换Paddle3.0.0的json格式paddle inference模型

使用PDX 3.0rc1 训练时序缺陷检测后导出的模型无法转换 Informations (please complete the following information): Inference engine for deployment: PD INFERENCE 3.0-->onnxruntime Why convert to onnx&#xff1a;在端侧设备上部署 Paddle2ONNX Version: 1.3.1 解…

React项目在ios和安卓端要做一个渐变色背景,用css不支持,可使用react-native-linear-gradient

以上有个模块是灰色逐渐到白的背景色过渡 如果是css&#xff0c;以下代码就直接搞定 background: linear-gradient(180deg, #F6F6F6 0%, #FFF 100%);但是在RN中不支持这种写法&#xff0c;那应该写呢&#xff1f; 1.引入react-native-linear-gradient插件&#xff0c;我使用的是…

【数据分析】特征工程-特征选择

【数据分析】特征工程-特征选择 &#xff08;一&#xff09;方差过滤法1.1 消除方差为0的特征1.2 保留一半的特征1.3 特征是二分类时 &#xff08;二&#xff09;相关性过滤法2.1 卡方过滤2.2 F检验2.3 互信息法 &#xff08;三&#xff09;其他3.1 包装法3.2 嵌入法3.3 衍生特…

uni-app 安卓消失的字符去哪里了?maxLength失效了!

前情提要 皮一下~这个标题我还蛮喜欢的嘿嘿嘿【附上一个自行思考的猥琐的笑容】 前段时间不是在开发uni-app的一个小应用嘛,然后今天测试发现,有一个地方在苹果是没有问题的,但是在安卓上出现了问题,附上安卓的截图 在这里我是有限制maxLength=50的,而且,赋值字符串到字…

嵌入式STM32学习——串口USART 2.0(printf重定义及串口发送)

printf重定义&#xff1a; C语言里面的printf函数默认输出设备是显示器&#xff0c;如果要实现printf函数输出正在串口或者LCD显示屏上&#xff0c;必须要重定义标准库函数里调用的与输出设备相关的函数&#xff0c;比如printf输出到串口&#xff0c;需要将fputc里面的输出指向…

【大模型】情绪对话模型项目研发

一、使用框架&#xff1a; Qwen大模型后端Open-webui前端实现使用LLamaFactory的STF微调数据集&#xff0c;vllm后端部署&#xff0c; 二、框架安装 下载千问大模型 安装魔塔社区库文件 pip install modelscope Download.py 内容 from modelscope import snapshot_downlo…

【PCI】PCI入门介绍(包含部分PCIe讲解)

先解释一下寻址空间&#xff1a; 机器是32bit的话&#xff0c;意味着4G&#xff08;2的32次方&#xff09;寻址空间&#xff0c;内存条作为它的实际物理存储设备。大部分在跑内存程序运行&#xff0c;少部分用来存放其他东西。这是一个常见的4G寻址空间分布&#xff08;不一定是…

使用PowerBI个人网关定时刷新数据

使用PowerBI个人网关定时刷新数据 PowerBI desktop连接mysql&#xff0c;可以设置定时刷新数据或在PowerBI服务中手动刷新数据,步骤如下&#xff1a; 第一步&#xff1a; 下载网关。以个人网关为例&#xff0c;如图 第二步&#xff1a; 双击网关&#xff0c;点击下一步&…

数字人引领政务新风尚:智能设备助力政务服务

在信息技术飞速发展的今天&#xff0c;政府机构不断探索提升服务效率和改善服务质量的新途径。实时交互数字人在政务服务中的应用正成为一大亮点&#xff0c;通过将“数字公务员”植入各种横屏智能设备中&#xff0c;为民众办理业务提供全程辅助。这种创新不仅优化了政务大厅的…