WPF Prism框架

Prism 是一个开源框架,专门用于开发可扩展、模块化和可测试的企业级 XAML 应用程序,适用于 WPF(Windows Presentation Foundation)和 Xamarin Forms 等平台。它基于 MVVM(Model-View-ViewModel)设计模式,提供一套丰富的工具和库,能够实现模块化、依赖注入、导航和事件聚合等功能。

Prism 的核心组件包括:

  1. 依赖注入(Dependency Injection):Prism 提供了一个依赖注入容器,可以将应用程序的组件和服务进行解耦,从而提高代码的可测试性和可维护性。
  2. 模块化(Modularity):Prism 支持模块化设计,将应用程序分解成独立的模块,每个模块负责特定的功能,有助于减少应用程序的复杂性,并能够使开发和维护更加容易。
  3. 导航(Navigation):Prism 提供了一个灵活的导航系统,可以定义视图之间的导航路径,并管理视图的生命周期。
  4. 事件聚合器(Event Aggregator):这是一个松散耦合的事件发布/订阅机制,应用程序的不同部分之间进行通信,而不需要直接引用对方。
  5. 命令(Commands):Prism 提供了一种简化的方式来处理用户界面中的命令,如按钮点击事件。
  6. 数据绑定(Data Binding):虽然 Prism 本身不提供数据绑定机制,但它与 WPF 和 Xamarin.Forms 的数据绑定框架紧密集成,可以轻松地将视图模型与视图进行绑定。

安装 Prism

Prism 可以通过 NuGet 包管理器进行安装,主要安装三个 Prism.Core、Prism.Unity、Prism.Wpf。首先创建一个新的 WPF、Xamarin Forms、Uno 或 WinUI 项目,然后打开 NuGet 包管理器,右键点击项目 -> 选择"管理 NuGet 包"。安装 Prism 核心包 Prism.Core,安装容器包 Prism.UnityPrism.DryIoc(根据需求选择),然后安装平台包,例如 WPF 安装 Prism.Wpf

使用 Prism

在 WPF 项目中使用 Prism 时,需要进行以下步骤:

  1. 新建WPF项目:新建一个 WPF 项目,并根据上面完成 Prism 的安装。
  2. 重写 App.xaml:添加命名空间 xmlns:prism="http://prismlibrary.com/" 并继承 PrismApplication,删除 StartupUri="MainWindow.xaml
  3. 修改 App.xaml.cs:继承 PrismApplication,并重写 CreateShell 和 RegisterTypes 方法。CreateShell 方法返回应用程序的主窗口,RegisterTypes 方法用于注册需要的类型。
  4. 修改 MainWindow.xaml:添加命名空间 xmlns:prism="http://prismlibrary.com/" 并设置 prism:ViewModelLocator.AutoWireViewModel="True",Prism 框架会根据规则自动查找该视图相对应 ViewModel。

通过这些步骤,你可以在 WPF 项目中集成 Prism 框架,实现 MVVM 架构和模块化开发。

 priam的依赖注入

Prism 框架中的依赖注入(Dependency Injection)是一种实现控制反转(Inversion of Control, IoC)的机制,它允许开发者将组件和服务的创建和管理从应用程序代码中分离出来,从而提高代码的可测试性和可维护性。以下是 Prism 依赖注入的一些关键点:

  1. PrismApplication 和依赖注入: Prism 项目中的 App 类继承自 PrismApplication,必须重写 CreateShell()RegisterTypes() 方法。RegisterTypes() 方法用于依赖注入容器,该方法使用 IContainerRegistry 类型的对象将用户自定义的对象注入容器。

  2. 内置依赖注入: Prism 源码中已经向 IoC 容器注入了一些核心服务,如 IApplicationProviderIEventAggregatorINavigationService 等,这些服务可以在窗体中通过构造函数直接注入对象。

  3. 自定义服务注入: 如果需要将自定义服务注入 Prism 容器,可以在 App.xaml.cs 中重写 RegisterTypes() 方法,通过 IContainerRegistry 类型的对象将自定义的服务注入 IoC 容器。例如,注册一个 MD5Provider 服务:

    protected override void RegisterTypes(IContainerRegistry containerRegistry)
    {containerRegistry.Register<MD5Provider>();
    }

    然后在需要使用该服务的地方,通过构造函数从 IoC 容器里将对象解析出来:

    public IndexViewModel(IContainerExtension container)
    {MD5Provider provider = container.Resolve<MD5Provider>();
    }
  4. 依赖注入的几种方法

    • Register:每次解析都会创建一个新的实例。
    • RegisterSingleton:整个应用程序生命周期内只创建一个实例(单例)。
    • RegisterScoped:在同一个 Scope 内只初始化一个实例。
  5. 模块化依赖注入: 可以为服务创建一个模块描述文件,继承接口 IModule,在模块描述文件中进行依赖注入。然后在 App.xaml.cs 中重写 ConfigureModuleCatalog 方法加载模块,实现模块的整体注入。

prism的模块化 

Prism 框架的模块化是一种将应用程序分解成独立、可重用模块的设计方法,这样可以提高应用程序的可维护性、可测试性和可扩展性。以下是 Prism 模块化的一些关键概念和步骤:

1. 模块的定义和特点

  • 独立性:每个模块负责特定的功能,并且与其他模块保持低耦合。
  • 可重用性:模块可以独立于主应用程序进行开发、测试和部署。
  • 低耦合:模块之间的依赖关系最小化,有利于维护和扩展。

2. 模块的加载流程

加载模块的流程通常包括以下几个步骤:

  1. 注册模块:在应用程序中注册模块,以便 Prism 框架可以发现和加载它们。
  2. 发现模块:Prism 框架会根据注册信息发现模块。
  3. 加载模块:根据需要加载模块,可以是按需加载或在应用程序启动时加载。
  4. 初始化模块:模块被加载后,会进行初始化,完成模块的设置和配置。

3. 模块的注册方式

Prism 提供了多种模块注册方式:

  • 代码注册:直接在代码中注册模块,这种方式简单直接,易于控制。
  • 目录文件扫描注册:Prism 可以扫描指定目录下的模块并自动注册。
  • 配置文件注册:通过配置文件(如 App.config)来注册模块,这种方式可以在不修改代码的情况下调整模块的加载。

4. 模块的实现

一个典型的 Prism 模块实现包括以下几个部分:

  • 模块类:实现 IModule 接口,定义模块的初始化和注册类型。
  • 视图和视图模型:模块中包含的视图和视图模型,用于实现模块的用户界面和业务逻辑。
  • 服务和依赖注入:在模块中注册服务,并使用依赖注入来管理这些服务。

5. 代码示例

以下是一个简单的 Prism 模块实现示例:

[Module(ModuleName = "MedicineModule", OnDemand = true)]
public class MedicineModule : IModule
{public void OnInitialized(IContainerProvider containerProvider){var regionManager = containerProvider.Resolve<IRegionManager>();regionManager.RegisterViewWithRegion(RegionNames.MedicineMainContentRegion, typeof(MedicineMainContent));}public void RegisterTypes(IContainerRegistry containerRegistry){// 在这里注册模块中需要的服务和类型}
}

在这个示例中,MedicineModule 类标记为一个 Prism 模块,并实现了 IModule 接口。在 OnInitialized 方法中,模块会注册视图到特定的区域。RegisterTypes 方法用于注册模块中需要的服务和类型,例如视图模型、服务等。

 prism的导航

Prism 框架的导航机制是其核心功能之一,它允许应用程序在不同的视图(View)或视图模型(ViewModel)之间进行切换,以实现用户界面的动态更新和功能模块的加载。以下是 Prism 导航机制的一些关键点:

1. 导航的基本概念

Prism 的导航不依赖于页面(Page)实例,而是通过一个唯一的标识符或键(key)来实现松耦合的导航。这意味着在 Prism 中,你不是直接导航到一个视图或视图模型,而是导航到一个代表目标视图的唯一标识符。

2. 定义域(Region)

在 Prism 中,导航通常是基于区域(Region)的概念。你可以使用 ContentControlItemsControl 及其子类来定义一个区域,并为这个区域命名。例如:

<ContentControl Grid.Row="1" Grid.ColumnSpan="2"prism:RegionManager.RegionName="ContentRegion"/>

这样,你就可以在代码中引用这个区域来进行导航。

3. 注册视图

在 Prism 中,你需要在依赖注入(DI)容器中注册视图,以便它们可以被导航到。Prism 提供了 RegisterTypeForNavigation 方法来实现这一点。例如,使用 Unity 容器注册视图:

_unityContainer.RegisterTypeForNavigation<CalendarView>();

这样,CalendarView 就可以被导航到了。

4. 导航操作

Prism 提供了 INavigationService 接口来处理导航请求。你可以通过调用 RequestNavigate 方法来导航到指定的视图。有两种主要的导航方式:

4.1 URI 导航
_regionManager.RequestNavigate("ContentRegion", calendarViewUri);

这里,ContentRegion 是目标区域的名称,calendarViewUri 是一个 Uri 类型的对象,表示需要导航到的视图的名称。

4.2 直接导航

你也可以直接通过视图的名称或自定义的键来导航:

_navigationService.NavigateAsync("MainPage");

这里的 "MainPage" 是注册时使用的键,用于标识要导航到的视图。

5. 自定义注册和导航

Prism 允许你自定义视图的注册和导航。你可以为视图提供一个唯一的键,而不是使用视图的名称作为键:

containerRegistry.RegisterForNavigation<MainPage>("CustomKey");

然后使用这个自定义的键来导航:

_navigationService.NavigateAsync("CustomKey");

这种方式提供了更多的灵活性,允许你根据需要自定义导航逻辑。

6. 跨平台导航

在跨平台应用中,Prism 允许你为不同的平台注册不同的视图,但使用相同的视图模型。这使得你可以为每个平台定制 UI,同时保持业务逻辑的一致性。

 prism的事件聚合器(Event Aggregator)

Prism框架中的事件聚合器(Event Aggregator)是一种松散耦合的事件发布/订阅机制,它允许组件之间进行通信,而不需要直接引用对方。以下是Prism事件聚合器的一些关键特性和使用方法:

1. 松散耦合的通信

事件聚合器允许发布者(publishers)和订阅者(subscribers)通过事件进行通信,而不需要知道对方的存在。这种机制基于事件聚合服务,支持多播发布/订阅功能,即可以有多个发布者触发同一个事件,也可以有多个订阅者监听同一个事件。

2. 类型安全的事件

Prism中的事件是类型安全的,这意味着你可以利用编译时类型检查来在运行应用程序之前检测错误。事件聚合器允许订阅者或发布者定位到特定的EventBase

3. IEventAggregator接口

EventAggregator类作为容器中的服务提供,可以通过IEventAggregator接口检索。事件聚合器负责定位或构建事件,并维护系统中事件的集合:

public interface IEventAggregator
{TEventType GetEvent<TEventType>() where TEventType : EventBase;
}

EventAggregator在首次访问时(如果尚未构建)会构建事件,这减轻了发布者或订阅者需要确定事件是否可用的负担。

4. PubSubEvent类

实际连接发布者和订阅者的工作由PubSubEvent类完成。这是Prism库中唯一实现EventBase类的类。这个类维护订阅者列表,并处理事件分发到订阅者。

5. 创建事件

PubSubEvent<TPayload>是应用程序或模块特定事件的基类。TPayload是事件负载的类型,即发布事件时传递给订阅者的参数。例如,以下代码展示了TickerSymbolSelectedEvent,其负载是一个包含公司符号的字符串:

public class TickerSymbolSelectedEvent : PubSubEvent<string>{}

在复合应用程序中,事件通常在多个模块之间共享,因此它们被定义在一个公共位置,如“Core”或“Infrastructure”项目中。

6. 发布事件

发布事件时,你可以通过EventAggregator获取事件实例,并调用Publish方法来发布事件。例如:

IEventAggregator eventAggregator = container.Resolve<IEventAggregator>();
eventAggregator.GetEvent<TickerSymbolSelectedEvent>().Publish("AAPL");

这样,所有订阅了TickerSymbolSelectedEvent的订阅者都会收到事件,并执行相应的逻辑。

prism的命令(Commands)

Prism框架中的命令(Commands)机制是实现MVVM模式中用户交互与视图模型逻辑分离的核心。以下是Prism命令机制的一些关键点:

1. Prism命令的基础

Prism提供了两种主要的命令类型:

  • DelegateCommand:一个简单的命令实现,适用于单个命令的场景。
  • CompositeCommand:可以将多个命令组合在一起,适用于需要多个命令同时执行的场景。

2. 使用DelegateCommand

2.1. 创建视图模型

在视图模型中创建一个DelegateCommand属性,指向一个方法。例如:

using Prism.Commands;
using Prism.Mvvm;public class MainViewModel : BindableBase
{public DelegateCommand MyCommand { get; private set; }public MainViewModel(){MyCommand = new DelegateCommand(OnMyCommandExecuted);}private void OnMyCommandExecuted(){// 命令执行时的逻辑System.Diagnostics.Debug.WriteLine("Command Executed!");}
}
2.2. 在XAML中绑定命令

在XAML中,可以将命令绑定到控件,如按钮:

<Button Content="Execute Command" Command="{Binding MyCommand}" />

这样,当按钮被点击时,就会执行绑定的命令。

3. 使用带参数的DelegateCommand

可以使用DelegateCommand<T>来处理命令参数。例如:

public DelegateCommand<string> MyParameterizedCommand { get; private set; }public MainViewModel()
{MyParameterizedCommand = new DelegateCommand<string>(OnMyParameterizedCommandExecuted);
}private void OnMyParameterizedCommandExecuted(string parameter)
{// 使用传递的参数System.Diagnostics.Debug.WriteLine($"Command Executed with parameter: {parameter}");
}

在XAML中绑定参数:

<Button Content="Execute with Parameter"Command="{Binding MyParameterizedCommand}"CommandParameter="Hello World" />

这样,当按钮被点击时,就会执行绑定的命令,并传递参数。

4. 使用CompositeCommand

CompositeCommand允许你将多个命令组合在一起,使得它们可以一起执行。例如:

public CompositeCommand MyCompositeCommand { get; private set; }
public DelegateCommand Command1 { get; private set; }
public DelegateCommand Command2 { get; private set; }public MainViewModel()
{MyCompositeCommand = new CompositeCommand();Command1 = new DelegateCommand(OnCommand1Executed);Command2 = new DelegateCommand(OnCommand2Executed);MyCompositeCommand.RegisterCommand(Command1);MyCompositeCommand.RegisterCommand(Command2);
}private void OnCommand1Executed()
{// 命令 1 执行逻辑
}private void OnCommand2Executed()
{// 命令 2 执行逻辑
}

在XAML中使用CompositeCommand

<Button Content="Execute Composite Command" Command="{Binding MyCompositeCommand}" />

这样,当按钮被点击时,就会同时执行Command1Command2

 prism的数据绑定(Data Binding)

Prism框架本身并不提供数据绑定的实现,因为它是建立在WPF、Xamarin.Forms、UWP等框架之上的,这些框架已经内置了数据绑定的功能。Prism通过与这些框架的集成,使得开发者可以利用它们强大的数据绑定机制来构建MVVM(Model-View-ViewModel)模式的应用程序。以下是Prism与数据绑定相关的一些关键点:

1. MVVM模式与数据绑定

MVVM模式是Prism推荐的架构模式,它将用户界面(View)与业务逻辑(ViewModel)分离,并通过数据绑定将它们连接起来。在MVVM中,View只负责显示,ViewModel包含业务逻辑和数据,数据绑定负责在View和ViewModel之间同步数据。

2. WPF中的数据绑定

在WPF中,数据绑定是通过Binding表达式实现的。例如,如果你想将一个文本框(TextBox)的Text属性绑定到ViewModel的Name属性,你可以这样写:

xml

<TextBox Text="{Binding Name}" />

Prism通过ViewModelLocator自动或手动将ViewModel与View关联起来,从而实现数据绑定。

3. Xamarin.Forms中的数据绑定

Xamarin.Forms也支持数据绑定,语法与WPF类似。例如:

xml

<Entry Text="{Binding Name}" />

Prism通过ViewModelLocatorBindingContext将ViewModel与页面(Page)关联起来。

4. Prism的ViewModelLocator

ViewModelLocator是Prism提供的一个附加属性,用于自动将ViewModel与View关联起来。例如,在WPF中,你可以在XAML中这样设置:

xml

<Window ...xmlns:prism="http://prismlibrary.com/"prism:ViewModelLocator.AutoWireViewModel="True"><!-- UI elements -->
</Window>

这样,Prism会自动创建ViewModel实例,并将其设置为View的DataContext

5. 数据转换

Prism与数据绑定框架一起使用时,可以利用数据转换器(Value Converters)来转换绑定的数据。例如,在Xamarin.Forms中,你可以创建一个转换器将布尔值转换为字符串:

csharp

public class BoolToStringConverter : IValueConverter
{public object Convert(object value, Type targetType, object parameter, CultureInfo culture){return (bool)value ? "Yes" : "No";}public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture){throw new NotImplementedException();}
}

然后在XAML中使用这个转换器:

xml

<Label Text="{Binding IsEnabled, Converter={StaticResource BoolToStringConverter}}" />

6. 命令绑定

Prism还支持命令绑定,允许你将UI元素(如按钮)的事件绑定到ViewModel中的命令。例如,在WPF中:

xml

<Button Command="{Binding SaveCommand}" Content="Save" />

这样,当按钮被点击时,就会执行ViewModel中的SaveCommand

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

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

相关文章

C#开发流程

注&#xff1a;检查数据库链接 设置搜索 1.新建模块文件夹 对应应用 右键-添加-新建文件夹 2.新建类 在新建模块下右键 新建-类&#xff0c;修改类名称 修改internal为public 新建所需字段&#xff0c;注意类型声明及必填设置 [SugarColumn(IsNullable false)]public strin…

区块链应用第1讲:基于区块链的智慧货运平台

基于区块链的智慧货运平台 网络货运平台已经比较成熟&#xff0c;提供了给货源方提供找司机的交易匹配方案&#xff1b;其中包含这几个角色&#xff1a;货主、承运人(司机、车队长)、监管机构、平台。司机要想接单&#xff0c;依赖于多个中心化的第三方平台&#xff0c;且三方平…

计算机毕业设计 | SpringBoot智慧⾼校学术报告系统 AI写作大模型生成平台(附源码)

1&#xff0c;项目介绍 智慧⾼校学术报告系统是⼀个基于 SpringBoot 开发的标准 Java Web 项⽬。系统整体⻚⾯设计简约⼤⽓&#xff0c;巧妙融合了⽬前备受瞩⽬的 AIGC ⽣成式 AI 技术&#xff0c;选择了阿⾥通⽤千问⼤语⾔模型&#xff0c;以智能⽣成趣味报告标题和润⾊报告内…

万字长文解读机器学习——决策树

&#x1f33a;历史文章列表&#x1f33a; 机器学习——损失函数、代价函数、KL散度机器学习——特征工程、正则化、强化学习机器学习——常见算法汇总机器学习——感知机、MLP、SVM机器学习——KNN机器学习——贝叶斯机器学习——决策树机器学习——随机森林、Bagging、Boostin…

在Django中安装、配置、使用CKEditor5,并将CKEditor5录入的文章展现出来,实现一个简单博客网站的功能

在Django中可以使用CKEditor4和CKEditor5两个版本&#xff0c;分别对应软件包django-ckeditor和django-ckeditor-5。原来使用的是CKEditor4&#xff0c;python manager.py makemigrations时总是提示CKEditor4有安全风险&#xff0c;建议升级到CKEditor5。故卸载了CKEditor4&…

实战项目:通过自我学习让AI学习五子棋 - 1 - 项目定义

项目介绍 五子棋是一种博弈游戏。在棋盘上黑子和白子交替落子&#xff0c;先于在任何方向上将至少五个棋子连在一起的一方获胜。在我们这个项目中我们尝试使用自学习的方法训练出一套走五子棋的算法。 这个项目本身并无特别大的实用价值。我们的目的在于&#xff1a; 尝试自…

从0开始搭建一个生产级SpringBoot2.0.X项目(十二)SpringBoot接口SpringSecurity JWT鉴权

前言 最近有个想法想整理一个内容比较完整springboot项目初始化Demo。 SpringBoot接口权限控制 SpringSecurity 接口使用 Bearer token类型 JWT 鉴权 一、pom文件新增依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>s…

JavaEE初阶---properties类+反射+注解

文章目录 1.配置文件properities2.快速上手3.常见方法3.1读取配置文件3.2获取k-v值3.3修改k-v值3.4unicode的说明 4.反射的引入4.1传统写法4.2反射的写法&#xff08;初识&#xff09;4.3反射的介绍4.4获得class类的方法4.5所有类型的class对象4.6类加载过程4.7类初始化的过程4…

【React】深入理解 JSX语法

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 深入理解 JSX语法1. JSX 简介2. JSX 的基本语法2.1 基本结构2.2 与普通 JavaScr…

Spark中给读取到的数据 的列 重命名的几种方式!

目录 一、第一种 (withColumnRenamed) 二、第二种&#xff08;toDF&#xff09; 三、第三种&#xff08; toDF(*tuple1) &#xff09; 四、 第四种(schema) 五、假如文件里自带有列名的情况&#xff08;option&#xff09; 一、第一种 (withColumnRenamed) 假设要把如下…

M1M2 MAC安装windows11 虚拟机的全过程

M1/M2 MAC安装windows11 虚拟机的全过程 这两天折腾了一下windows11 arm架构的虚拟机&#xff0c;将途中遇到的坑总结一下。 1、虚拟机软件&#xff1a;vmware fusion 13.6 或者 parallel 19 &#xff1f; 结论是&#xff1a;用parellel 19。 这两个软件都安装过&#xff0…

IEEE JSSC更新|Tiny Tapeout:让每个人都能设计定制芯片

简介 由于成本高昂且需要专业技术&#xff0c;设计和制造定制集成电路的传统上仅限于大型公司和机构。然而&#xff0c;名为Tiny Tapeout的创新项目正在改变这一现状&#xff0c;让业余爱好者、学生和小型团队也能设计定制芯片。本文将探讨Tiny Tapeout的工作原理&#xff0c;以…

Java:一段代码,无限可能

Java&#xff0c;诞生于1995年&#xff0c;如今已走过近三十载春秋。它历经互联网泡沫的兴衰、移动互联网的浪潮&#xff0c;以及云计算和大数据的洗礼&#xff0c;依然屹立在编程语言的舞台中央&#xff0c;散发着耀眼的光芒。这篇文章将带你回顾Java的辉煌历史&#xff0c;探…

《XGBoost算法的原理推导》12-14决策树复杂度的正则化项 公式解析

本文是将文章《XGBoost算法的原理推导》中的公式单独拿出来做一个详细的解析&#xff0c;便于初学者更好的理解。 我们定义一颗树的复杂度 Ω Ω Ω&#xff0c;它由两部分组成&#xff1a; 叶子结点的数量&#xff1b;叶子结点权重向量的 L 2 L2 L2范数&#xff1b; 公式(…

Linux【基础篇】

-- 原生罪 linux的入门安装学习 什么是操作系统&#xff1f; 用户通过操作系统和计算机硬件联系使用。桥梁~ 什么是Linux&#xff1f; 他是一套开放源代码&#xff08;在互联网上找到Linux系统的源代码&#xff0c;C语言写出的软件&#xff09;&#xff0c;可以自由 传播&…

大数据技术在智慧医疗中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 大数据技术在智慧医疗中的应用 大数据技术在智慧医疗中的应用 大数据技术在智慧医疗中的应用 引言 大数据技术概述 定义与原理 发…

Linux(CentOS)安装 MySQL

CentOS版本&#xff1a;CentOS 7 三种安装方式&#xff1a; 一、通过 yum 安装&#xff0c;最简单&#xff0c;一键安装&#xff0c;全程无忧。 二、通过 rpm 包安装&#xff0c;需具备基础概念及常规操作。 三、通过 gz 包安装&#xff0c;需具备配置相关操作。 --------…

CSS如何改变滚动条的颜色样式粗细?

默认滚动条很丑怎么办&#xff1f;如何改版滚动条的粗细&#xff0c;颜色&#xff0c;让它更美观&#xff1f;CSS如何改变滚动条的粗细&#xff1f; 干货来了 /* Webkit内核浏览器的滚动条样式 */ ::-webkit-scrollbar {width: 4px; /* 设置滚动条的宽度 */ }::-webkit-scroll…

YOLOv11(Ultralytics)可视化界面ui设计,基于pyqt5,单文件即插即用,支持文件夹检测及云摄像头检测并保存

本文的可视化界面对于YOLOv11/Ultralytics/YOLOv8的检测、分割、分类、姿势估算&#xff08;detection, segmentation, obb, classification, and pose estimation&#xff09;等均可正常显示。本次新增了图片及视频的保存&#xff0c;可以选择传入文件夹进行检测并显示&#x…

用python开发坦克大战重制版

Python 开发坦克大战重制版&#xff1a;全面教程 引言 坦克大战是一款经典的街机游戏&#xff0c;自1985年首次推出以来&#xff0c;便吸引了无数玩家。随着时间的推移&#xff0c;许多游戏开发者开始尝试重制这款经典游戏。本文将指导你如何使用 Python 和 Pygame 库开发一个…