资讯详情

egui 自定义样式实战:用 `style_mut_of` 打造双主题 UI(custom_style 示例解析)

📅 2026/9/11 7:43:31 | 华诺云谱 👁 阅读
egui 自定义样式实战:用 `style_mut_of` 打造双主题 UI(custom_style 示例解析)
egui 自定义样式实战用style_mut_of打造双主题 UIcustom_style 示例解析【免费下载链接】eguiegui: an easy-to-use immediate mode GUI in Rust that runs on both web and native项目地址: https://gitcode.com/GitHub_Trending/eg/eguiegui 是一款运行于原生与 Web 端的 Rust 即时模式 GUI 框架。本文基于仓库中 examples/custom_style 官方示例讲解如何通过Context::style_mut_of分别定制深色/浅色两套主题下的超链接色、文本光标色与选中态样式并借助global_theme_preference_buttons让用户在暗色、亮色与跟随系统之间一键切换。读完本文你将掌握 egui 样式系统的核心入口、Style/Visuals结构的关键字段以及如何在自己的应用中复刻这一套一套代码、两套皮肤的定制方案。示例概览与运行方式custom_style是一个极简但完整的 eframe 桌面应用它启动一个 350×590 的窗口内部以中央面板展示一句标题、一行主题切换按钮以及来自egui_demo_lib的WidgetGallery控件画廊用于直观呈现自定义样式在真实控件上的效果。运行方式READMEcargo run -p custom_style其依赖与特性配置见 examples/custom_style/Cargo.toml应用本体基于eframe启用__screenshot特性可在EFRAME_SCREENSHOT_TO环境变量下导出截图同时引入egui_demo_lib提供WidgetGallery演示控件与egui_extras其image特性用于安装图片加载器供控件画廊展示图片使用。注意publish false与edition 2024说明它只是工作区内的示例工程而非可发布的 crate。样式的两条定制路线egui 中修改外观风格有两条主要路径二者在 context.rs 与 style.rs 中均有体现全局定制调用ctx.style_mut_of(theme, |style| { ... })或ctx.all_styles_mut(...)修改整个应用所有新创建 UI 的默认风格局部定制通过Ui::style_mut、ui.visuals_mut()或Frame的StyleModifier见 style.rs 中StyleModifier的定义仅影响某个Ui及其子控件。custom_style示例采用全局定制应用在启动时一次性设置好两套主题的样式运行期间不再改动随后交给用户切换主题。style_mut_of按主题定制样式的核心入口示例的样式设置集中在setup_custom_style函数中main.rsfn setup_custom_style(ctx: egui::Context) { ctx.style_mut_of(Theme::Light, use_light_green_accent); ctx.style_mut_of(Theme::Dark, use_dark_purple_accent); }style_mut_of的实现位于 context.rspub fn style_mut_of(self, theme: Theme, mutate_style: impl FnOnce(mut Style)) { self.options_mut(|opt| match theme { Theme::Dark mutate_style(Arc::make_mut(mut opt.dark_style)), Theme::Light mutate_style(Arc::make_mut(mut opt.light_style)), }); }理解这段实现需要抓住三个要点双主题独立存储egui 在Options中维护dark_style与light_style两份独立的ArcStyle。style_mut_of按传入的Theme选取对应的一份再用Arc::make_mut实现写时复制copy-on-write避免每次修改都克隆整棵样式树一次性修改全局生效闭包会在options_mut内部执行修改结果持久保存此后所有新建的弹出层、菜单、面板都会读取这份样式Context::style_mut_of的文档注释明确说明mutate the style used by all subsequent popups, menus, etc.Theme只是开关Theme枚举见 memory/theme.rs只有Dark与Light两个成员它决定当前该用哪套默认样式而style_mut_of负责预先改好这套默认样式。Theme还提供了default_style()与default_visuals()两个便捷方法memory/theme.rs分别返回某主题的默认Style与默认Visuals——如果你不想在默认基础上修改而是想从零构建一套风格可以以这两个方法的返回值为起点。修改的具体字段超链接、文本光标与选中态两套主题的定制函数都只改了三个字段全部位于style.visualsVisuals结构见 style.rs。下面以亮色绿色主题use_light_green_accent为例main.rsfn use_light_green_accent(style: mut Style) { style.visuals.hyperlink_color Color32::from_rgb(18, 180, 85); style.visuals.text_cursor.stroke.color Color32::from_rgb(28, 92, 48); style.visuals.selection Selection { bg_fill: Color32::from_rgb(157, 218, 169), stroke: Stroke::new(1.0, Color32::from_rgb(28, 92, 48)), }; }三个字段的底层定义如下hyperlink_color定义在 style.rs是所有Hyperlink控件的统一颜色text_cursor类型为TextCursorStylestyle.rs其stroke决定文本光标的颜色与宽度。egui 内置的亮色/暗色默认值分别见 style.rs例如暗色默认光标色为Color32::from_rgb(0, 83, 125)且宽度为 2.0selection类型为Selectionstyle.rsbg_fill是选中文本或可选中按钮的背景色stroke是选中态的描边颜色。注意示例用Stroke::new(1.0, ...)将描边宽度显式设为 1.0 像素。亮色与暗色两套配色的完整对照如下源码见 main.rs字段亮色绿暗色紫hyperlink_color(18, 180, 85)绿色(202, 135, 227)紫色text_cursor.stroke.color(28, 92, 48)深绿(234, 208, 244)浅紫selection.bg_fill(157, 218, 169)浅绿(105, 67, 119)深紫selection.stroke1.0px(28, 92, 48)1.0px(234, 208, 244)这种暗色主题配高饱和亮色、亮色主题配深色强调色的做法保证了两种模式下超链接与选中态都有足够的对比度。让用户在主题间切换global_theme_preference_buttons样式定制完成后示例在 UI 中放入了一行主题切换按钮main.rsegui::CentralPanel::default().show(ui, |ui| { ui.heading(egui using a customized style); ui.label(Switch between dark and light mode to see the different styles in action.); global_theme_preference_buttons(ui); ui.separator(); self.widget_gallery.ui(ui); });global_theme_preference_buttons定义于 widgets/mod.rs它读取Context::options().theme_preference渲染ThemePreference的三个选项按钮并将用户的选择写回pub fn global_theme_preference_buttons(ui: mut Ui) { let mut theme_preference ui.options(|opt| opt.theme_preference); theme_preference.buttons(ui); ui.ctx().set_theme(theme_preference); }ThemePreference枚举memory/theme.rs包含三个成员Dark、Light以及默认值System跟随操作系统主题。其buttons方法在水平布局中渲染三个图标按钮 / ☀️ / 见 memory/theme.rs当前选项高亮显示每个按钮带说明性的悬浮提示。相比之下旧版global_theme_preference_switch只有明暗两个按钮、无法切回跟随系统因此已被标记为废弃widgets/mod.rs新代码应直接使用global_theme_preference_buttons。这里正是双主题定制发挥作用的关键由于亮/暗两套Style已分别被style_mut_of修改过set_theme切换Theme时无需任何额外代码控件会自动套用对应主题下的绿色或紫色强调色——这也解释了示例界面中那句Switch between dark and light mode to see the different styles in action的含义。应用启动流程与其余细节main函数main.rs展示了 eframe 应用的完整启动骨架fn main() - eframe::Result { env_logger::init(); // Log to stderr (if you run with RUST_LOGdebug). let options eframe::NativeOptions { viewport: egui::ViewportBuilder::default().with_inner_size([350.0, 590.0]), ..Default::default() }; eframe::run_native( egui example: custom style, options, Box::new(|cc| Ok(Box::new(MyApp::new(cc)))), ) }env_logger::init()初始化日志可用RUST_LOGdebug cargo run -p custom_style观察调试输出ViewportBuilder::with_inner_size([350.0, 590.0])设定初始窗口尺寸MyApp::new在拿到CreationContext后立刻调用setup_custom_style(cc.egui_ctx)——必须在首帧绘制之前完成全局样式设置这正是通过CreationContext而非App生命周期来挂接的原因随后调用egui_extras::install_image_loaders(cc.egui_ctx)安装图片加载器供控件画廊中的图片控件使用。MyApp仅持有一个WidgetGallery定义于 crates/egui_demo_lib/src/demo/widget_gallery.rs通过eframe::App::ui回调渲染注意该示例用的是新的ui方法而非传统的update方法。控件画廊覆盖了按钮、滑块、复选框、颜色选择器等常见控件恰好能全面检验自定义样式在不同交互状态普通/悬停/按下/选中下的观感。在自己的应用中复刻此方案将示例迁移到自己的 eframe 工程只需三步定义按主题区分的定制函数为Theme::Light与Theme::Dark各写一个fn(mut Style)闭包如use_light_green_accent/use_dark_purple_accent那样统一修改visuals下的颜色字段在CreationContext中挂接在eframe::run_native的创建闭包里调用setup_custom_style(cc.egui_ctx)把两套主题分别用ctx.style_mut_of(Theme::Light, ...)与ctx.style_mut_of(Theme::Dark, ...)写入暴露切换入口在界面任意位置放置egui::global_theme_preference_buttons(ui)让用户能切到暗色/亮色/跟随系统。从源码层面看这套方案之所以成立是因为 egui 将当前主题与每套主题的默认样式解耦Theme决定取用哪套默认样式style_mut_of负责预先改写这些默认值set_theme只负责切换。理解了这个数据流见 context.rs 与 memory/theme.rs你就能举一反三同样的机制也可以用来为两套主题定制间距style.spacing.item_spacing、字号style.text_styles乃至字体族style.override_font_id具体字段说明可查阅 style.rs 中Style结构的完整定义。【免费下载链接】eguiegui: an easy-to-use immediate mode GUI in Rust that runs on both web and native项目地址: https://gitcode.com/GitHub_Trending/eg/egui创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。