首页/新闻资讯/正文详情

深度解析 Druid:一款 data-first 的 Rust 原生 UI 工具包(基于 0.8.3 源码)

发布时间:2026/9/24 15:25:23 来源:云帆数科 栏目:资讯中心
深度解析 Druid:一款 data-first 的 Rust 原生 UI 工具包(基于 0.8.3 源码)
跨平台桌面应用UI组件【免费下载链接】druidA>项目地址https://gitcode.com/gh_mirrors/drui/druid点击查看免费下载本篇以仓库根目录 README.md 为骨架结合 druid 源码、druid-shell 与 druid-derive 实现细节系统讲解 Druid 的核心架构druid-shell / piet / widgets / layout / Data / Lens、快速上手方式、平台支持与构建配置以及其项目现状与继承者 Xilem。读完你将掌握如何在 Rust 项目中接入 Druid、理解其>use druid::widget::{Button, Flex, Label}; use druid::{AppLauncher, LocalizedString, PlatformError, Widget, WidgetExt, WindowDesc}; fn main() - Result(), PlatformError { let main_window WindowDesc::new(ui_builder()); let data 0_u32; AppLauncher::with_window(main_window) .log_to_console() .launch(data) } fn ui_builder() - impl Widgetu32 { // The label text will be computed dynamically based on the current locale and count let text LocalizedString::new(hello-counter).with_arg(count, |data: u32, _env| (*data).into()); let label Label::new(text).padding(5.0).center(); let button Button::new(increment) .on_click(|_ctx, data, _env| *data 1) .padding(5.0); Flex::column().with_child(label).with_child(button) }这个例子直观展示了>druid 0.8.3在 druid/src/lib.rs 的文档中还给出了带 feature 的写法[dependencies.druid] version 0.8.3 features [im, svg, image]平台说明LinuxDruid 依赖 gtk3需要先安装 GTK 开发库。基于 Ubuntu 的发行版执行sudo apt-get install libgtk-3-devOpenBSD同样需要 gtk3通过包管理器安装pkg_add gtk3此外还有一个X11 后端可供尝试但目前缺失不少功能可通过 feature 启用cargo run --featuresx11注意 druid/Cargo.toml 中默认 feature 为gtkx11与wayland都属于非默认的可选后端。Feature 矩阵在源码中有明确声明wayland被标注为not ready for the prime time. Many things dont work yet.非常实验性。可选的 feature 体系从 druid/src/lib.rs 的 Optional Features 文档与 druid/Cargo.toml 的[features]段可以整理出完整的 feature 矩阵工具类 featureim高效不可变数据结构基于imcrate以druid::im模块 re-exportsvg基于usvg/resvg/tiny-skia的可缩放矢量图支持图标等image基于imagecrate 的位图支持x11实验性 X11 后端替代 GTKwayland实验性 Wayland 后端serde部分内部类型主要是 kurbo 基础几何类型的 Serde 支持raw-win-handle为WindowHandle实现HasRawWindowHandlechrono时间类型chrono::Duration、NaiveDate等的Data实现。图片格式 featurepng、jpeg、gif、bmp、ico、tiff、webp、pnm、dds、tga、hdr以及一键开启全部格式的image-all。源码注释特别说明不支持 AVIF因为 Druid 仅使用图片的decode解码能力。Windows 应用注意默认情况下 Windows 会为应用同时打开控制台窗口若不需要在 crate 顶部添加#![windows_subsystem windows]。设计目标Goals与非目标Non-GoalsGoalsDruid 的目标是让开发者在所有常见平台上轻松编写并部署体验流畅顺滑的高质量桌面应用为此追求在所有受支持平台上易于构建与打包提供抽象层以规避平台特有的怪异差异quirks尊重平台约定与用户预期以很小的成本可靠处理显示分辨率与缩放支持简单而强大的国际化i18n提供稳健的无障碍accessibility支持产出小体积、快速度、低内存占用的二进制拥有小依赖树、高质量代码库与良好组织聚焦于强大的桌面级应用提供灵活的布局与常用控件集合便于按需创建自定义组件与应用逻辑。Non-Goals为了达成上述目标Druid 不可能支持所有场景README 明确列出了非目标及社区替代方案使用平台原生控件或模仿它们 → 替代[Relm]、[Slint]轻易嵌入自定义渲染管线 → 替代[Conrod]遵循特定架构风格如 Elm→ 替代[Iced]、[Relm]面向 Web 时渲染成 HTML → 替代[Iced]、[Moxie]Druid 只是当时众多 [Rust-native GUI 实验] 之一。核心概念与源码级解析druid-shell平台抽象层Druid 通过druid-shell获得平台抽象的应用外壳。它的职责是启动原生平台 runloop、监听事件、将其转换为平台无关的表示、并调用用户提供的处理器。在 druid-shell 中可以看到完整的后端矩阵backend/gtk、backend/mac、backend/x11、backend/wayland、backend/web、backend/windows以及共享的键盘/定时器抽象。每个后端都提供application、window、clipboard、menu、dialog、screen等模块。虽然 druid-shell 是为 Druid 工具包开发的但它被设计得足够通用可供其他 Rust GUI 实验项目复用——例如 druid-shell/examples/shello.rs 就是一个不依赖 druid 的独立示例。piet2D 图形与文本布局Druid 依赖Piet 库进行绘制与文本布局。Piet 是 2D 图形抽象拥有多个后端piet-direct2d、piet-coregraphics、piet-cairo、piet-web、piet-svg。Druid 的平台映射为macOS →piet-coregraphicsLinux / OpenBSD / FreeBSD →piet-cairoWindows →piet-direct2dWeb →piet-webREADME 给出了一个直接使用 piet/kurbo API 的绘制示例通常在自定义控件的paint中调用ctx.size()返回当前绘制区域的布局尺寸use druid::kurbo::{BezPath, Point, Rect}; use druid::piet::Color; // Create an arbitrary bezier path // (ctx.size() returns the size of the layout rect were painting in) let mut path BezPath::new(); path.move_to(Point::ORIGIN); path.quad_to( (80.0, 90.0), (ctx.size().width, ctx.size().height), ); // Create a color let stroke_color Color::rgb8(0x00, 0x80, 0x00); // Stroke the path with thickness 1.0 ctx.stroke(path, stroke_color, 1.0); // Rectangles: the path for practical people let rect Rect::from_origin_size((10., 10.), (100., 100.)); // Note the Color:rgba8 which includes an alpha channel (7F in this case) let fill_color Color::rgba8(0x00, 0x00, 0x00, 0x7F); ctx.fill(rect, fill_color);在 druid/src/lib.rs 中kurbo与piet通过pub use druid_shell::{kurbo, piet};直接 re-export并额外导出Affine、Insets、Point、Rect、Size、Vec2、Color、ImageBuf、LinearGradient、RadialGradient、RenderContext、UnitPoint等常用绘图类型因此用户通常不需要直接依赖 piet/kurbo。widgets控件与 Widget traitDruid 中的控件文本框、按钮、布局组件等都是实现了Widgettrait的对象。该 trait 以关联数据类型T参数化所有 trait 方法都能访问这份数据其中event拿到的是可变引用事件可以直接更新数据。每当应用数据变化时框架会以update方法遍历控件层级。所有 trait 方法都配有对应的上下文EventCtx、LifeCycleCtx、UpdateCtx、LayoutCtx、PaintCtx控件通过调用上下文的方法来请求行为同时所有方法都提供环境Env其中包含当前主题参数颜色、尺寸等。README 展示了Widgettrait 的完整签名以ButtonT为例implT: Data WidgetT for ButtonT { fn event(mut self, ctx: mut EventCtx, event: Event, data: mut T, env: Env) { ... } fn lifecycle(mut self, ctx: mut LifeCycleCtx, event: LifeCycle, data: T, env: Env) { ... } fn update(mut self, ctx: mut UpdateCtx, old_data: T, data: T, env: Env) { ... } fn layout(mut self, ctx: mut LayoutCtx, bc: BoxConstraints, data: T, env: Env) - Size { ... } fn paint(mut self, ctx: mut PaintCtx, data: T, env: Env) { ... } }从 druid/src/widget/widget.rs 的源码文档可以进一步看到各方法的职责细节event处理Event枚举中的各类事件可以请求EventCtx行为、修改数据或提交Commandlifecycle处理与控件图结构或控件自身状态相关的生命周期通知不应在此时修改应用状态需要修改时可提交Command延后执行update数据或环境变化时调用可通过UpdateCtx::request_paint/request_layout精确安排重绘旧数据值会被传入以便计算细粒度增量可通过env_changed/env_key_changed判断Env变化layout叶子控件确定满足约束的尺寸并返回容器控件递归调用子控件的WidgetPod::layout并设置原点布局策略深受 Flutter 启发paint通过PaintCtxderef 到RenderContext绘制外观容器可在递归子控件前绘制背景、之后绘制覆盖层如滚动条并可施加蒙版与变换对滚动尤其有用。容器控件通常不直接调用子控件的 trait 方法而是持有包裹在WidgetPod中的子控件并调用WidgetPod上的对应方法——WidgetPod负责决定是否递归等逻辑。源码中Widget还隐含了WidgetId基于NonZeroU64的唯一标识自动为参与布局的每个WidgetPod分配可用于通过submit_commandTarget在控件间通信。Druid 提供了大量基础工具与布局控件见 druid/src/widget 目录Flex、Label、Button、TextBox、Scroll、Split、Tabs、List、SizedBox、Padding、Align等也很容易实现自定义控件或将控件组合成新控件fn build_widget() - impl Widgetu32 { let mut col Flex::column(); for i in 0..30 { let button Button::new(format!(Button {}, i).padding(5.0); col.add_child(button); } Scroll::new(col) }注README 原文中该示例的Button::new(...)少了一个右括号实际编译时应写为Button::new(format!(Button {}, i)).padding(5.0)。layoutFlutter 风格的盒约束布局Druid 的布局协议强烈借鉴了 Flutter 的 box layout model。控件会收到一个BoxConstraints提供布局的最小与最大尺寸控件还负责为子控件计算合适的约束如果适用。从 druid/src/box_constraints.rs 源码可以看到BoxConstraints内部就是min: Size与max: Size两个字段约束总是朝远离零的方向取整到整数以实现像素级精确布局Size::expand提供UNBOUNDED任意非负尺寸都可满足、new、tight只能满足唯一尺寸、loosen最小尺寸归零、constrain把尺寸 clamp 进约束区间等构造与操作方法Widget::layout方法签名中的bc: BoxConstraints即为该约束对象。容器的典型流程是递归调用子控件的layout可自由选择顺序例如先算非 flex 控件的尺寸再决定 flex 控件可用的剩余空间计算布局后对每个子控件调用set_origin最后返回容器自身的尺寸。为了效率容器应对每个子控件只调用一次 layout。dataData trait 与值类型Druid 用Datatrait表示值类型value types。这些类型应当比较便宜、克隆便宜。核心方法只有一个samefn same(self, other: Self) - bool;从 druid/src/data.rs 的 trait 文档可以提炼关键语义same是设计为总是快速的操作若返回true则两个值必须相等但两个相等的值不一定same例如分别分配的两份拷贝通常不视为 same这里 equal 的含义与PartialEq略有不同例如两个 NaN 浮点数在位表示相同时应视为相等——因此f32/f64的same用to_bits()比较而非标准库中大量基础类型整数、bool、char、String、时间类型、Arc/Rc指针相等、Option、Result、元组、数组、Range族以及 kurbo 几何类型、piet 颜色/字体类型都已实现Datastd集合类型没有Data实现因为比较它们可能很昂贵。有两个简单替代方案把集合包进Arc或开启imfeature——它会为imcrate 的不可变集合Vector、HashMap、OrdMap等添加Data实现。im的实现对Vector做了优化小到可以内联inline时逐元素比较否则用指针相等ptr_eq见 druid/src/data.rs 第 562-573 行。一般情况下可以直接用derive生成Data实现#[derive(Clone, Data)] struct AppState { which: bool, value: f64, }derive 宏还支持字段属性详见 druid-derive 的 derive 文档与 tests/data.rs 测试#[data(ignore)]跳过该字段的same比较如缓存、时间戳等不属于数据模型的部分#[data(same_fn path)]为某字段指定自定义比较函数签名需为fn(T, T) - bool实际使用中还有#[data(eq)]等便捷属性文档示例中用#[data(eq)]让无Data实现的PathBuf直接按相等性比较C 风格枚举纯单元变体生成的实现会检查相等性因此此类类型还必须实现PartialEq。Data是 Druid 数据流的核心正因为有了same框架才能判断数据是否真的变化从而决定是否触发update遍历Widgettrait 的T: Data约束即源于此。lens聚焦大数据结构的一部分Lens数据类型用于访问更大的数据结构中的一部分。与Data一样它也可以通过 derive 生成派生出的 lens 以与字段同名的关联常量形式访问。#[derive(Clone, Data, Lens)] struct AppState { which: bool, value: f64, }要使用 lens用LensWrap包裹控件即可注意AppState::value由 CamelCase 类型名自动转换而来LensWrap::new(WidgetThatExpectsf64::new(), AppState::value);对于结构体、元组和可索引容器还可以随时用lens!宏按需构造 lensLensWrap::new(WidgetThatExpectsf64::new(), lens!(AppState, value));这在处理定义在另一个 crate 里的类型时特别有用无法给别人的类型加 derive。从 druid/src/lens/lens.rs 源码看LensT, Utrait 只有两个方法都以闭包而非返回值的方式工作with(self, data: T, f: FnOnce(U) - V) - V对字段做只读访问。之所以设计成闭包形式而非直接返回引用是为了允许 lens 按需临时合成数据with_mut(self, data: mut T, f: FnOnce(mut U) - V) - V对字段做可变访问。设计成闭包是因为要配合值类型/不可变数据结构使用——例如不可变 list 的 lens 可以先克隆 list、让闭包修改克隆、闭包返回后再更新原引用。LensExt提供了组合与变换能力见 druid/src/lens/mod.rs 导出的Field、Identity、Index、Map、Then、Deref、InArc、Constant、Unit等get/put拷贝或写回目标值then将LensA, B与LensB, C组合成LensA, C如lens!(Foo, x).then(lens!((u32, bool), 1))map用一对正反函数把一个不存在于原始结构中的计算值适配成 lens例如把 0-2 范围的值映射给范围 0-1 的Slider使用deref调用类型的Deref实现还有index等针对可索引容器的 lens。WidgetExt::lens扩展方法如TextBox::new().lens(MyState::search_term)内部即用LensWrap包装让一个WidgetString变成WidgetMyState典型场景是把TextBox嵌入数据模型不是String的更大结构中。应用启动流程AppLauncher 源码解读README 示例中的AppLauncher::with_window(...).log_to_console().launch(data)背后是 druid/src/app.rs 中的完整启动链路AppLauncher::with_window(window: WindowDescT)用给定窗口描述创建启动器内部维护窗口列表、可选的env_setup、l10n 资源、AppDelegate与扩展事件宿主WindowDesc::title(impl IntoLabelTextT)设置窗口标题接受String、LocalizedString或计算字符串的闭包会随应用状态变化保持更新不调用时默认标题为LocalizedString::new(app-name)WindowConfig::window_size(size: impl IntoSize)设置初始窗口尺寸单位为显示点 display points平台可能因 DPI 略有调整Windows 上另有兼容处理log_to_console()等价于start_console_logging(true)launch(data: T)真正创建Application、构建Env含 i18n 资源、装配控件树并启动平台 runloop若窗口无法实例化则返回PlatformError通常是致命错误。这也解释了为什么main()的返回类型是Result(), PlatformError。总结何时值得学习 DruidDruid 的源码约 40 余个示例、druid-shell的六套后端、druid-derive的 derive 宏与 UI 测试、以及 druid/tests 中的布局/失效测试是一份质量相当高的 Rust GUI 教学材料。它的>赞分享跨平台桌面应用UI组件【免费下载链接】druidA>项目地址https://gitcode.com/gh_mirrors/drui/druid点击查看免费下载相关推荐探索 Druid一款创新的 Rust 原生 UI 工具包探索 Druid一款创新的 Rust 原生 UI 工具包 THE 0TH POSITION OF THE ORIGINAL IMAGE 在寻找一个性能卓越、功跨平台桌面应用UI组件WarcraftHelper终极指南如何让经典魔兽争霸3在现代电脑上流畅运行WarcraftHelper终极指南如何让经典魔兽争霸3在现代电脑上流畅运行 你是否还在为魔兽争霸3的卡顿、低帧率和兼容性问题而烦恼这款经典RTS游戏虽然已跨平台桌面应用UI组件如何快速上手Camelidae-8x13B5分钟完成文本生成推理实战教程如何快速上手Camelidae 8x13B5分钟完成文本生成推理实战教程 Camelidae 8x13B是一款基于参数高效稀疏构建技术的大语言模型采用创新的上一篇IDM激活脚本终极指南3分钟掌握完整使用方法下一篇AI视频生成终极指南5分钟快速部署Wan2.2-I2V-A14B创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

DevilutionX(暗黑破坏神 1)GKD350h 移植版:安装、按键映射与已知问题全解析
DevilutionX(暗黑破坏神 1)GKD350h 移植版:安装、按键映射与已知问题全解析

游戏开发 【免费下载链接】DevilutionX Diablo build for modern operating systems 项目地址: https://gitcode.com/gh_mirrors/de/DevilutionX 点击查看 免费下载 DevilutionX 是《暗黑破坏神 1》面向现代操作系统的开源重制移植,本指南聚焦其在 GKD3… · 2026/9/24 15:25:23

命题专家答题方法哪里学 技巧答题赛道哪家更靠谱
命题专家答题方法哪里学 技巧答题赛道哪家更靠谱

不少初高中家长都会遇到这样的困惑:孩子课本上的知识都能看懂,日常学习也投入不少精力,但面对试卷作答时,很难把自身积累充分展现出来。刷了大量习题,学习状态却没有明显改观,这往往不是孩子不够用心&#… · 2026/9/24 15:25:23

勾芡香菇汤做法详解:一碗汤品从菜谱到 RAG 知识库的完整旅程
勾芡香菇汤做法详解:一碗汤品从菜谱到 RAG 知识库的完整旅程

教程人工智能大模型RAG 【免费下载链接】all-in-rag 🔍大模型应用开发实战一:RAG 技术全栈指南,在线阅读地址:https://datawhalechina.github.io/all-in-rag/ 项目地址: https://gitcode.com/datawhalechina/all-in-ra… · 2026/9/24 15:25:17

DRF 3.x Filtering 过滤使用示例和配置方法
DRF 3.x Filtering 过滤使用示例和配置方法

在开发过程中,数据过滤是必不可少的功能。无论是进行数据展示、查询,还是处理大量数据时,通过过滤可以提高数据处理的效率,提升用户体验。在Django框架的DRF(Django Rest Framework)中,提供了一系列强大且灵活的过滤工具,方便开发者为API添加查询过滤、排序等功能。本文… · 2026/9/24 16:00:31

xiaozhi-esp32-server 接入 Fish Speech 语音合成:AutoDL 云端部署与本地 TTS 配置实战
xiaozhi-esp32-server 接入 Fish Speech 语音合成:AutoDL 云端部署与本地 TTS 配置实战

xiaozhi-esp32-server 接入 Fish Speech 语音合成:AutoDL 云端部署与本地 TTS 配置实战 【免费下载链接】xiaozhi-esp32-server 本项目为xiaozhi-esp32提供后端服务,帮助您快速搭建ESP32设备控制服务器。Backend service for xiaozhi-esp32, helps you q… · 2026/9/24 16:00:18

408计算机考研资源全景:51份章节PDF+两年刷题本+笔记,全在这个仓库
408计算机考研资源全景:51份章节PDF+两年刷题本+笔记,全在这个仓库

408计算机考研资源全景:51份章节PDF两年刷题本笔记,全在这个仓库 【免费下载链接】cs-408 计算机考研专业课程408相关的复习经验,资源和OneNote笔记 项目地址: https://gitcode.com/GitHub_Trending/cs/cs-408 这个仓库是408计算机考研… · 2026/9/24 16:00:12

Semi Design DragMove 组件完全指南:拖拽移动、范围约束与自定义位置处理
Semi Design DragMove 组件完全指南:拖拽移动、范围约束与自定义位置处理

Semi Design DragMove 组件完全指南:拖拽移动、范围约束与自定义位置处理 【免费下载链接】semi-design 🚀A modern, comprehensive, flexible design system and React UI library, AI-friendly built-in.🎨Provide 3000 Design Tokens, eas… · 2026/9/24 16:00:12

go-swagger 贡献者入门指南:从源码构建、运行测试到提交首个 Pull Request
go-swagger 贡献者入门指南:从源码构建、运行测试到提交首个 Pull Request

代码生成开发工具后端API设计 【免费下载链接】go-swagger Swagger 2.0 implementation for go 项目地址: https://gitcode.com/gh_mirrors/go/go-swagger 点击查看 免费下载 本篇指南面向希望参与 go-swagger 开发与维护的开发者,完整讲解开发环境搭建… · 2026/9/24 16:00:12

Salt JSON 输出模块(json_out)实战指南:从 CLI 参数到源码级缩进与解析原理
Salt JSON 输出模块(json_out)实战指南:从 CLI 参数到源码级缩进与解析原理

运维配置管理后端 【免费下载链接】salt Software to automate the management and configuration of infrastructure and applications at scale. 项目地址: https://gitcode.com/gh_mirrors/sa/salt 点击查看 免费下载 导读 Salt 的输出器(outputter… · 2026/9/24 16:00:12

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为… · 2026/9/24 0:00:13

1D-CNN时间序列建模实战:从Conv1d原理到工业落地
1D-CNN时间序列建模实战:从Conv1d原理到工业落地

简介:面向时间序列数据建模的一维卷积神经网络完整实现,适合深度学习入门者及需要快速验证时序模型的研究者,能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小,只有3KB,内含3个Python脚… · 2026/9/24 0:00:26

柔软的L:汉语语流中被忽视的舌肌张力控制
柔软的L:汉语语流中被忽视的舌肌张力控制

1. 这个“L”不是字母表里的L,而是舌尖上的L最近在几个方言群和语音教学社群里,反复看到有人发一句:“也说字母L:柔软的长舌”。初看以为是英语发音课笔记,点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码