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

跨平台WPF音乐商店应用程序

目录

一 简介

二 设计思路

三 源码


一 简介

支持在线检索音乐,支持实时浏览当前收藏的音乐及音乐数据的持久化。

二 设计思路

采用MVVM架构,前后端分离,子界面弹出始终位于主界面的中心。

三 源码

视窗引导启动源码:

namespace Avalonia.MusicStore
{public class ViewLocator : IDataTemplate{public Control? Build(object? data){if (data is null)return null;var name = data.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal);var type = Type.GetType(name);if (type != null){var control = (Control)Activator.CreateInstance(type)!;control.DataContext = data;return control;}return new TextBlock { Text = "Not Found: " + name };}public bool Match(object? data){return data is ViewModelBase;}}
}using Avalonia;
using Avalonia.ReactiveUI;
using System;namespace Avalonia.MusicStore
{internal sealed class Program{// Initialization code. Don't use any Avalonia, third-party APIs or any// SynchronizationContext-reliant code before AppMain is called: things aren't initialized// yet and stuff might break.[STAThread]public static void Main(string[] args) => BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);// Avalonia configuration, don't remove; also used by visual designer.public static AppBuilder BuildAvaloniaApp()=> AppBuilder.Configure<App>().UsePlatformDetect().WithInterFont().LogToTrace().UseReactiveUI();}
}

模型源码:

using iTunesSearch.Library;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;namespace Avalonia.MusicStore.Models
{public class Album{private static iTunesSearchManager s_SearchManager = new();public string Artist { get; set; }public string Title { get; set; }public string CoverUrl { get; set; }public Album(string artist, string title, string coverUrl){Artist = artist;Title = title;CoverUrl = coverUrl;}public static async Task<IEnumerable<Album>> SearchAsync(string searchTerm){var query = await s_SearchManager.GetAlbumsAsync(searchTerm).ConfigureAwait(false);return query.Albums.Select(x =>new Album(x.ArtistName, x.CollectionName,x.ArtworkUrl100.Replace("100x100bb", "600x600bb")));}private static HttpClient s_httpClient = new();private string CachePath => $"./Cache/{Artist} - {Title}";public async Task<Stream> LoadCoverBitmapAsync(){if (File.Exists(CachePath + ".bmp")){return File.OpenRead(CachePath + ".bmp");}else{var data = await s_httpClient.GetByteArrayAsync(CoverUrl);return new MemoryStream(data);}}public async Task SaveAsync(){if (!Directory.Exists("./Cache")){Directory.CreateDirectory("./Cache");}using (var fs = File.OpenWrite(CachePath)){await SaveToStreamAsync(this, fs);}}public Stream SaveCoverBitmapStream(){return File.OpenWrite(CachePath + ".bmp");}private static async Task SaveToStreamAsync(Album data, Stream stream){await JsonSerializer.SerializeAsync(stream, data).ConfigureAwait(false);}public static async Task<Album> LoadFromStream(Stream stream){return (await JsonSerializer.DeserializeAsync<Album>(stream).ConfigureAwait(false))!;}public static async Task<IEnumerable<Album>> LoadCachedAsync(){if (!Directory.Exists("./Cache")){Directory.CreateDirectory("./Cache");}var results = new List<Album>();foreach (var file in Directory.EnumerateFiles("./Cache")){if (!string.IsNullOrWhiteSpace(new DirectoryInfo(file).Extension)) continue;await using var fs = File.OpenRead(file);results.Add(await Album.LoadFromStream(fs).ConfigureAwait(false));}return results;}}
}

模型视图源码:

using Avalonia.Media.Imaging;
using Avalonia.MusicStore.Models;
using ReactiveUI;
using System.Threading.Tasks;namespace Avalonia.MusicStore.ViewModels
{public class AlbumViewModel : ViewModelBase{private readonly Album _album;public AlbumViewModel(Album album){_album = album;}public string Artist => _album.Artist;public string Title => _album.Title;private Bitmap? _cover;public Bitmap? Cover{get => _cover;private set => this.RaiseAndSetIfChanged(ref _cover, value);}public async Task LoadCover(){await using (var imageStream = await _album.LoadCoverBitmapAsync()){Cover = await Task.Run(() => Bitmap.DecodeToWidth(imageStream, 400));}}public async Task SaveToDiskAsync(){await _album.SaveAsync();if (Cover != null){var bitmap = Cover;await Task.Run(() =>{using (var fs = _album.SaveCoverBitmapStream()){bitmap.Save(fs);}});}}}
}
using Avalonia.MusicStore.Models;
using ReactiveUI;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive.Concurrency;
using System.Reactive.Linq;
using System.Windows.Input;namespace Avalonia.MusicStore.ViewModels
{public class MainWindowViewModel : ViewModelBase{public ICommand BuyMusicCommand { get; }public Interaction<MusicStoreViewModel, AlbumViewModel?> ShowDialog { get; }public ObservableCollection<AlbumViewModel> Albums { get; } = new();public MainWindowViewModel(){ShowDialog = new Interaction<MusicStoreViewModel, AlbumViewModel?>();BuyMusicCommand = ReactiveCommand.CreateFromTask(async () =>{var store = new MusicStoreViewModel();var result = await ShowDialog.Handle(store);if (result != null){Albums.Add(result);await result.SaveToDiskAsync();}});RxApp.MainThreadScheduler.Schedule(LoadAlbums);}private async void LoadAlbums(){var albums = (await Album.LoadCachedAsync()).Select(x => new AlbumViewModel(x));foreach (var album in albums){Albums.Add(album);}foreach (var album in Albums.ToList()){await album.LoadCover();}}}
}
using Avalonia.MusicStore.Models;
using ReactiveUI;
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive;
using System.Reactive.Linq;
using System.Threading;namespace Avalonia.MusicStore.ViewModels
{public class MusicStoreViewModel : ViewModelBase{private string? _searchText;private bool _isBusy;public string? SearchText{get => _searchText;set => this.RaiseAndSetIfChanged(ref _searchText, value);}public bool IsBusy{get => _isBusy;set => this.RaiseAndSetIfChanged(ref _isBusy, value);}private AlbumViewModel? _selectedAlbum;public ObservableCollection<AlbumViewModel> SearchResults { get; } = new();public AlbumViewModel? SelectedAlbum{get => _selectedAlbum;set => this.RaiseAndSetIfChanged(ref _selectedAlbum, value);}public MusicStoreViewModel(){this.WhenAnyValue(x => x.SearchText).Throttle(TimeSpan.FromMilliseconds(400)).ObserveOn(RxApp.MainThreadScheduler).Subscribe(DoSearch!);BuyMusicCommand = ReactiveCommand.Create(() =>{return SelectedAlbum;});}private async void DoSearch(string s){IsBusy = true;SearchResults.Clear();_cancellationTokenSource?.Cancel();_cancellationTokenSource = new CancellationTokenSource();var cancellationToken = _cancellationTokenSource.Token;if (!string.IsNullOrWhiteSpace(s)){var albums = await Album.SearchAsync(s);foreach (var album in albums){var vm = new AlbumViewModel(album);SearchResults.Add(vm);}if (!cancellationToken.IsCancellationRequested){LoadCovers(cancellationToken);}}IsBusy = false;}private async void LoadCovers(CancellationToken cancellationToken){foreach (var album in SearchResults.ToList()){await album.LoadCover();if (cancellationToken.IsCancellationRequested){return;}}}private CancellationTokenSource? _cancellationTokenSource;public ReactiveCommand<Unit, AlbumViewModel?> BuyMusicCommand { get; }}
}
using ReactiveUI;namespace Avalonia.MusicStore.ViewModels
{public class ViewModelBase : ReactiveObject{}
}

视图源码:

<UserControlx:Class="Avalonia.MusicStore.Views.AlbumView"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"xmlns:vm="using:Avalonia.MusicStore.ViewModels"Width="200"d:DesignHeight="450"d:DesignWidth="800"x:DataType="vm:AlbumViewModel"mc:Ignorable="d"><StackPanel Width="200" Spacing="5"><Border ClipToBounds="True" CornerRadius="10"><Panel Background="#7FFF22DD"><ImageWidth="200"Source="{Binding Cover}"Stretch="Uniform" /><Panel Height="200" IsVisible="{Binding Cover, Converter={x:Static ObjectConverters.IsNull}}"><PathIconWidth="75"Height="75"Data="{StaticResource music_regular}" /></Panel></Panel></Border><TextBlock HorizontalAlignment="Center" Text="{Binding Title}" /><TextBlock HorizontalAlignment="Center" Text="{Binding Artist}" /></StackPanel>
</UserControl>
<Windowx:Class="Avalonia.MusicStore.Views.MainWindow"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"xmlns:views="clr-namespace:Avalonia.MusicStore.Views"xmlns:vm="using:Avalonia.MusicStore.ViewModels"Title="Avalonia.MusicStore"d:DesignHeight="450"d:DesignWidth="800"x:DataType="vm:MainWindowViewModel"Background="Transparent"ExtendClientAreaToDecorationsHint="True"Icon="/Assets/avalonia-logo.ico"TransparencyLevelHint="AcrylicBlur"WindowStartupLocation="CenterScreen"mc:Ignorable="d"><Panel><ExperimentalAcrylicBorder IsHitTestVisible="False"><ExperimentalAcrylicBorder.Material><ExperimentalAcrylicMaterialBackgroundSource="Digger"MaterialOpacity="0.65"TintColor="Black"TintOpacity="1" /></ExperimentalAcrylicBorder.Material></ExperimentalAcrylicBorder><Panel Margin="40"><ButtonHorizontalAlignment="Right"VerticalAlignment="Top"Command="{Binding BuyMusicCommand}"><PathIcon Data="{StaticResource store_microsoft_regular}" /></Button><ItemsControl Margin="0,40,0,0" ItemsSource="{Binding Albums}"><ItemsControl.ItemsPanel><ItemsPanelTemplate><WrapPanel /></ItemsPanelTemplate></ItemsControl.ItemsPanel><ItemsControl.ItemTemplate><DataTemplate><views:AlbumView Margin="0,0,20,20" /></DataTemplate></ItemsControl.ItemTemplate></ItemsControl></Panel></Panel></Window>
using Avalonia.MusicStore.ViewModels;
using Avalonia.ReactiveUI;
using ReactiveUI;
using System.Threading.Tasks;namespace Avalonia.MusicStore.Views
{public partial class MainWindow : ReactiveWindow<MainWindowViewModel>{public MainWindow(){InitializeComponent();this.WhenActivated(action => action(ViewModel!.ShowDialog.RegisterHandler(DoShowDialogAsync)));}private async Task DoShowDialogAsync(InteractionContext<MusicStoreViewModel,AlbumViewModel?> interaction){var dialog = new MusicStoreWindow();dialog.DataContext = interaction.Input;var result = await dialog.ShowDialog<AlbumViewModel?>(this);interaction.SetOutput(result);}}
}
<UserControlx:Class="Avalonia.MusicStore.Views.MusicStoreView"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"xmlns:vm="using:Avalonia.MusicStore.ViewModels"d:DesignHeight="450"d:DesignWidth="800"x:DataType="vm:MusicStoreViewModel"mc:Ignorable="d"><DockPanel><StackPanel DockPanel.Dock="Top"><TextBox Text="{Binding SearchText}" Watermark="Search for Albums...." /><ProgressBar IsIndeterminate="True" IsVisible="{Binding IsBusy}" /></StackPanel><ButtonHorizontalAlignment="Center"Command="{Binding BuyMusicCommand}"Content="Buy Album"DockPanel.Dock="Bottom" /><ListBoxMargin="0,20"Background="Transparent"ItemsSource="{Binding SearchResults}"SelectedItem="{Binding SelectedAlbum}"><ListBox.ItemsPanel><ItemsPanelTemplate><WrapPanel /></ItemsPanelTemplate></ListBox.ItemsPanel></ListBox></DockPanel>
</UserControl>
<Windowx:Class="Avalonia.MusicStore.Views.MusicStoreWindow"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"xmlns:views="using:Avalonia.MusicStore.Views"Title="MusicStoreWindow"Width="1000"Height="550"ExtendClientAreaToDecorationsHint="True"TransparencyLevelHint="AcrylicBlur"WindowStartupLocation="CenterOwner"mc:Ignorable="d"><Panel><ExperimentalAcrylicBorder IsHitTestVisible="False"><ExperimentalAcrylicBorder.Material><ExperimentalAcrylicMaterialBackgroundSource="Digger"MaterialOpacity="0.65"TintColor="Black"TintOpacity="1" /></ExperimentalAcrylicBorder.Material></ExperimentalAcrylicBorder><Panel Margin="40"><views:MusicStoreView /></Panel></Panel>
</Window>
using Avalonia.MusicStore.ViewModels;
using Avalonia.ReactiveUI;
using ReactiveUI;
using System;namespace Avalonia.MusicStore.Views
{public partial class MusicStoreWindow : ReactiveWindow<MusicStoreViewModel>{public MusicStoreWindow(){InitializeComponent();this.WhenActivated(action => action(ViewModel!.BuyMusicCommand.Subscribe(Close)));}}
}

相关文章:

跨平台WPF音乐商店应用程序

目录 一 简介 二 设计思路 三 源码 一 简介 支持在线检索音乐&#xff0c;支持实时浏览当前收藏的音乐及音乐数据的持久化。 二 设计思路 采用MVVM架构&#xff0c;前后端分离&#xff0c;子界面弹出始终位于主界面的中心。 三 源码 视窗引导启动源码&#xff1a; namesp…...

设计模式简述(一)

定义&#xff1a;设计模式指的是在软件开发过程中&#xff0c;经过验证的&#xff0c;用于解决在特定环境下&#xff0c;重复出现的&#xff0c;特定问题的解决方案。创建型设计模式关注对象的创建过程&#xff0c;提供了更灵活、可扩展的对象创建机制。结构型设计模式用于解决…...

OSI参考模型:解析网络通信的七层框架

引言 在现代计算机网络中&#xff0c;OSI&#xff08;开放式系统互联&#xff09;参考模型是理解和设计网络通信协议的基础。1978年由国际标准化组织&#xff08;ISO&#xff09;提出&#xff0c;OSI模型定义了网络通信的七层结构&#xff0c;每一层都承担着特定的功能&#x…...

QT通用配置文件库(QPreferences)

QT通用配置文件库(QPreferences) QPreferences项目是基于nlohmann/json的qt可视化配置文件库&#xff0c;将配置保存成json格式&#xff0c;并提供UI查看与修改&#xff0c;可通过cmake可快速添加进项目。默认支持基本类型、stl常用容器、基本类型与stl容器组成的结构体&#…...

如何搭建一个RADIUS服务器?

1. 系统环境 1.1.操作系统 Ubuntu-20.04.1 &#xff08;kernel: 5.15.0-58-generic&#xff09; 1.2.所需软件 FreeRADIUS MariaDB 1.3.注意事项 本文提到的所有操作&#xff0c;都是以root 身份执行&#xff1b; 2. FreeRADIUS的安装 2.1. 安装FreeRADIUS服务器程序 以…...

双机热备综合实验

1&#xff0c;对现有网络进行改造升级&#xff0c;将当个防火墙组网改成双机热备的组网形式&#xff0c;做负载分担模式&#xff0c;游客区和DMZ区走FW3&#xff0c;生产区和办公区的流量走FW1 2&#xff0c;办公区上网用户限制流量不超过100M&#xff0c;其中销售部人员在其基…...

Java和Python的图结构如何实现图的深度优先搜索算法

Java和Python的图结构如何实现图的深度优先搜索算法&#xff1f; 在Java和Python中&#xff0c;实现深度优先搜索&#xff08;DFS&#xff09;算法的基本思路都是通过递归或栈来探索图的各个节点。 Java实现DFS&#xff1a;Java import java.util.ArrayList; import java.uti…...

Web学习day05

html&css 目录 html&css 文章目录 一、web开发 1.1工作流程 1.2开发技术 二、HTML 2.1HTML规范 2.2基础标签 2.2.1标题 2.2.2水平线 2.2.3段落和换行 2.2.4文字效果 2.2.5超链接 2.2.6图像 2.2.7音频和视频 三、布局标签 3.1列表 3.2容器 3.3表格 3…...

LINUX客户端client(socket、connect)实现客户端发送,服务器接收

SERVICE端见前一篇文章 5. 客户端连接函数 connect()&#xff08;与前面的bind一样&#xff09; int connect (int sockfd, struct sockaddr * serv_addr, int addrlen) 参数&#xff1a; sockfd: 通过 socket() 函数拿到的 fd addr:struct sockaddr 的结构体变量地址 addr…...

【网络安全科普】勒索病毒 防护指南

勒索病毒简介 勒索病毒是一种恶意软件&#xff0c;也称为勒索软件&#xff08;Ransomware&#xff09;&#xff0c;其主要目的是在感染计算机后加密用户文件&#xff0c;并要求用户支付赎金以获取解密密钥。这种类型的恶意软件通常通过电子邮件附件、恶意链接、下载的软件或漏洞…...

TFHE库,fftw和googletest库安装

点个关注吧&#xff01;本文主要关注于TFHE的安装与常见的问题 1.TFHE的git链接&#xff1a; https://github.com/tfhe/tfhe git clone --recurse-submodules --branchmaster https://github.com/tfhe/tfhe.git 2.安装 mkdir build cd build cmake ../src -DENABLE_TESTSon -D…...

关于Spring Boot IOCDC,看这一篇就够了

一&#xff0c;Spring是什么及常用注解 先说什么是spring&#xff0c;在前面的博客中已经知道了&#xff0c;spring是一个开源框架&#xff0c;为了让我们开发更加简单&#xff0c;那关于ioc呢&#xff0c;一句话概况一下&#xff1a;Spring就是包含了众多工具方法的Ioc容器 …...

Model Import Settings

前言 在可视化3D世界中&#xff0c;模型是3D世界的核心&#xff0c;你可以没有贴图&#xff0c;可以没有特效&#xff0c;甚至可以没有用户交互界面&#xff0c;但必须得有模型来描述世界的基本样貌。 在3D世界中&#xff0c;由点线面构成了模型的轮廓&#xff1b;由UV和纹理&a…...

腾讯云COS托管静态网站,以及如何解决访问出现了下载网页的情况

腾讯云对象存储&#xff08;Cloud Object Storage&#xff0c;简称COS&#xff09;&#xff0c;与其他云厂商所提供的云对象存储都是面向非结构化数据&#xff0c;只是每个云厂商的叫法有别于他家&#xff0c;或许是更能彰显厂商的品牌吧&#xff01; 但不管云厂商怎么给云对象…...

软件设计模式: 抽象工厂

抽象工厂 一、解决的问题 抽象工厂模式主要解决了在具有多个产品族的情况下&#xff0c;如何统一管理创建相关产品对象的问题。 当系统需要创建一系列相互关联或相互依赖的对象&#xff0c;并且这些对象可以形成多个不同的产品族时&#xff0c;如果直接由客户端去分别创建这…...

使用Vuepress搭建个人网站

网站地址&#xff1a;bloggo.chat...

lua 写一个 不同时区之间转换日期和时间 函数

这个函数用于调整时间戳以适应不同的时区。它接受五个参数&#xff1a;format、timeStamp、dontFixForTimeOffset、currentServerTimeZone和showLog。返回 os.date&#xff0c;可以转化成指定格式的年月日时间 ### 功能 该函数的主要功能是根据给定的时区偏移量调整时间戳&am…...

谷粒商城——session共享

问题1 一个系统中不同微服务的session共享。 问题1的解决办法 1. session复制的方法&#xff1a;微服务的副本之间通过通信共享session。这样每一个微服务的副本都会保存所有的session。&#xff08;缺点&#xff1a;造成大量的通信&#xff0c;多处额外的通信开销。&#x…...

Java 语言及其常用集合类的操作,以及反射机制与注解

目录 一、Java 语言概述 二、Java 集合框架 ArrayList 操作示例&#xff1a; HashMap 操作示例&#xff1a; 三、反射机制 1. 反射的示例 五、总结 Java 是一种广泛使用的高级编程语言&#xff0c;因其平台独立性、简洁性及丰富的 API 而备受开发者青睐。 一、Java 语言…...

《系统架构设计师教程(第2版)》第12章-信息系统架构设计理论与实践-02-信息系统架构

文章目录 1. 概述1.1 信息系统架构&#xff08;ISA&#xff09;1.2 架构风格 2. 信息系统架构分类2.1 信息系统物理结构2.1.1 集中式结构2.1.2 分布式结构 2.2 信息系统的逻辑结构1&#xff09;横向综合2&#xff09;纵向综合3&#xff09;纵横综合 3. 信息系统架构的一般原理4…...

上周刚把三菱PLC+MCGS的电机测速课设收尾,趁着热乎劲把细节唠唠,顺便把踩过的坑也记一下,省得下次忘光

No.1235 基于三菱 PLC和MCGS组态电机测速系统控制设计这个项目说白了就是用三菱PLC算电机的转速&#xff0c;再用MCGS组态屏把转速实时显示出来&#xff0c;用到的东西挺基础&#xff1a;FX3U PLC、1000线增量式编码器、直流减速电机、MCGS组态屏&#xff0c;再加一根USB转RS48…...

如何让实验室管理“更简单”?——King’s LIMS以灵活与智能,重构高效运营新范式

在日常实验室管理中&#xff0c;流程繁琐、数据难溯源、报告生成低效、多场景管控混乱等问题&#xff0c;常成为拖慢运营节奏、抬升运维成本的“隐形阻力”。要打破管理困局、实现轻量化高效运维&#xff0c;选对数字化工具是关键。然而&#xff0c;在选择LIMS的过程中&#xf…...

百川2-13B-4bits模型微调实践:提升OpenClaw特定任务准确率

百川2-13B-4bits模型微调实践&#xff1a;提升OpenClaw特定任务准确率 1. 为什么需要微调百川模型&#xff1f; 去年冬天&#xff0c;当我第一次用OpenClaw自动整理电脑上的技术文档时&#xff0c;发现了一个尴尬的问题&#xff1a;模型总是把Python代码片段误判为"待办…...

计算机毕业设计springboot校园互助平台 基于SpringBoot的高校学生互助服务系统 SpringBoot框架下的校园协同帮助平台

计算机毕业设计springboot校园互助平台3m6f99 &#xff08;配套有源码 程序 mysql数据库 论文&#xff09;本套源码可以先看具体功能演示视频领取&#xff0c;文末有联xi 可分享近年来&#xff0c;随着互联网技术的蓬勃发展和智慧校园建设的深入推进&#xff0c;高校学生对于便…...

MATLAB Simulink代码生成全流程详解:涵盖环境配置、参数与信号配置、函数名配置、数...

matlab simulink代码生成 包括&#xff1a;环境配置&#xff0c;参数与信号配置&#xff0c;函数名配置&#xff0c;数据管理&#xff0c;代码生成&#xff0c;以及代码优化等 文档63页把Simulink模型变成可烧录的C代码&#xff0c;这事儿听起来挺玄乎&#xff0c;但只要你踩过…...

vLLM实战:手把手教你用LLMEngine构建高效推理服务(附代码解析)

vLLM实战&#xff1a;从零构建高性能大模型推理服务的工程指南 当大语言模型从实验室走向生产环境时&#xff0c;如何实现高吞吐、低延迟的推理服务成为工程化落地的关键挑战。vLLM作为当前最受关注的开源推理框架之一&#xff0c;其核心组件LLMEngine的设计理念值得每一位AI工…...

EN50155以太网交换机的X键位M12插座在PCB板上同一高度方法

在轨道交通车载EN50155以太网交换机的PCB设计中&#xff0c;X键位M12插座&#xff08;千兆/万兆接口&#xff09;常需多个并排或阵列布局。由于X编码插座引脚数较多&#xff08;8芯&#xff09;且结构复杂&#xff0c;确保所有插座在PCB板上的同一高度&#xff08;共面性&#…...

MusePublic大模型Qt图形界面开发指南

MusePublic大模型Qt图形界面开发指南 1. 为什么需要图形界面&#xff1f; 如果你已经能用代码调用MusePublic大模型&#xff0c;可能会发现一个问题&#xff1a;每次都要打开终端、输入命令、等待结果&#xff0c;这样的交互方式既不方便也不直观。特别是当你需要频繁调整参数…...

如何实现SASM多语言支持:完整国际化配置与翻译指南

如何实现SASM多语言支持&#xff1a;完整国际化配置与翻译指南 【免费下载链接】SASM SASM - simple crossplatform IDE for NASM, MASM, GAS and FASM assembly languages 项目地址: https://gitcode.com/gh_mirrors/sa/SASM SASM&#xff08;Simple Assembler IDE&…...

从松到深:解析组合导航三大模式的演进路径与实战选型

1. 组合导航的底层逻辑与技术演进 第一次接触组合导航系统时&#xff0c;我被这个看似简单的概念惊艳到了——把两种完全不同的定位技术融合在一起&#xff0c;竟然能产生11>2的效果。这就像做菜时的黄金搭档&#xff0c;比如西红柿和鸡蛋单独吃都不错&#xff0c;但炒在一起…...