egui(发音为“e-gooey”)是一个简单、快速且高度可移植的 Rust 即时模式 GUI 库。egui 在 Web 上运行,本机运行,并在你最喜欢的游戏引擎中运行(或即将运行)。
egui 旨在成为最容易使用的 Rust GUI 库,也是在 Rust 中制作 Web 应用程序的最简单方法。
egui 可以在任何可以绘制纹理三角形的地方使用,这意味着你可以轻松地将其集成到你选择的游戏引擎中。
部分:
ui.heading("My egui Application");
ui.horizontal(|ui| {
ui.label("Your name: ");
ui.text_edit_singleline(&mut name);
});
ui.add(egui::Slider::new(&mut age, 0..=120).text("age"));
if ui.button("Click each year").clicked() {
age += 1;
}
ui.label(format!("Hello '{}', age {}", name, age));
examples/ 文件夹中
有简单的例子。如果要编写 Web 应用,请转到 https://github.com/emilk/eframe_template/ 并按照说明进行操作。官方文档在 https://docs.rs/egui。有关灵感和更多示例,请查看 egui Web 演示并按照其中的链接访问其源代码。
如果要将 egui 集成到现有引擎中,请转到集成部分。
如有疑问,请使用 GitHub 讨论。还有一个 egui 不和谐服务器。如果你想为 egui 做出贡献,请阅读贡献指南。
单击以运行egui Web演示(适用于任何支持WASM和WebGL的浏览器)。使用 eframe
。
要在本地测试演示应用程序,请运行 。
cargo run --release -p egui_demo_app
本机后端是egui_glow
的(使用glow
),应该在Mac和Windows上开箱即用,但在Linux上,你需要首先运行:
sudo apt-get install -y libclang-dev libgtk-3-dev libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev libspeechd-dev libxkbcommon-dev libssl-dev
在Fedora Rawhide上,你需要运行:
dnf install clang clang-devel clang-tools-extra speech-dispatcher-devel libxkbcommon-devel pkg-config openssl-devel libxcb-devel
注意:这仅适用于演示应用程序 - egui 本身完全与平台无关!
epaint
) 的简单 2D 图形 API。unsafe
ab_glyph
ahash
nohash-hasher
parking_lot
egui 不是一个框架。egui 是你调用的库,而不是你为其编程的环境。
注意:egui 并没有声称已经达到了所有这些目标!egui 仍在进行中。
egui 旨在成为你想要一种创建 GUI 的简单方法或想要将 GUI 添加到游戏引擎时的最佳选择。
如果你没有使用 Rust,egui 不适合你。如果你想要一个看起来原生的 GUI,egui 不适合你。如果你想要在升级时不会损坏的东西,egui 不适合你(还)。
但是,如果你正在用 Rust 编写一些需要简单 GUI 的交互式东西,egui 可能适合你。
egui 的明显替代品是 imgui-rs
,它是围绕C++库 Dear ImGui 的 Rust 包装器。Dear ImGui 是一个很棒的库(也是 egui 的主要灵感来源),具有更多的功能和润色。但是,egui 为 Rust 用户提供了一些好处:
imgui-rs
egui 还尝试以其他小方式改善你的体验:
所以总结一下:
egui 正在积极开发中。它适用于它的功能,但它缺乏许多功能,并且界面仍在不断变化。新版本将具有重大更改。
灯光主题:
egui 易于集成到你正在使用的任何现有游戏引擎或平台中。egui 本身不知道也不关心它正在运行什么操作系统或如何将内容呈现到屏幕上 - 这是 egui 集成的工作。
集成需要在每个帧中执行以下操作:
这些是官方的 egui 集成:
eframe
,用于将相同的应用程序编译为Web/wasm和桌面/本机。用途和 .egui_glow
egui-winit
egui_glium
用于使用 Glium 编译本机应用程序。egui_glow
用于在本机和 web 上呈现发光的 egui,以及用于制作本机应用程序。egui-wgpu
for wgpu (WebGPU API).egui-winit
用于与 winit 集成。amethyst_egui
紫水晶游戏引擎。bevy_egui
用于Bevy游戏引擎。egui_glfw_gl
GLFW。egui-glutin-gl 用于glutin
。egui_sdl2_gl
SDL2。egui_sdl2_platform
SDL2。egui_vulkano
为武尔卡诺。egui_winit_vulkano
为武尔卡诺。egui-macroquad
for macroquad。egui-miniquadfor Miniquad.
egui_speedy2d
Speedy2d。egui-tetra
for Tetra,一个2D游戏框架。egui-winit-ash-integration
for winit and ash。fltk-eguifor fltk-rs.
ggez-eguifor the ggez game framework.
godot-eguifor godot-rust.
nannou_egui
为南诺。notan_egui
诺坦。屏幕 13-egui
用于屏幕 13。egui_skia
滑雪板。-埃吉
为史密斯。缺少你正在处理的事情的集成?创建一个,这很容易!
你需要收集 egui::RawInput
并处理 egui::FullOutput
。基本结构是这样的:
let mut egui_ctx = egui::CtxRef::default();
// Game loop:
loop {
// Gather input (mouse, touches, keyboard, screen size, etc):
let raw_input: egui::RawInput = my_integration.gather_input();
let full_output = egui_ctx.run(raw_input, |egui_ctx| {
my_app.ui(egui_ctx); // add panels, windows and widgets to `egui_ctx` here
});
let clipped_primitives = egui_ctx.tessellate(full_output.shapes); // creates triangles to paint
my_integration.paint(&full_output.textures_delta, clipped_primitives);
let platform_output = full_output.platform_output;
my_integration.set_cursor_icon(platform_output.cursor_icon);
if !platform_output.copied_text.is_empty() {
my_integration.set_clipboard_text(platform_output.copied_text);
}
// See `egui::FullOutput` and `egui::PlatformOutput` for more
}
有关 OpenGL 后端的参考,请参阅egui_glium
画家或egui_glow
画家。
pixels_per_point
(ONE, ONE_MINUS_SRC_ALPHA)
GL_CLAMP_TO_EDGE
GL_SRGB8_ALPHA8
GL_FRAMEBUFFER_SRGB
egui是即时模式 GUI 库,而不是保留模式 GUI 库。保留模式和即时模式之间的区别最好地用按钮示例来说明:在保留的 GUI 中,你创建一个按钮,将其添加到某个 UI 并安装一些单击处理程序(回调)。该按钮保留在 UI 中,要更改其上的文本,你需要存储对它的某种引用。相比之下,在即时模式下,你可以立即显示按钮并立即与之交互,并且每帧都这样做(例如每秒 60 次)。这意味着不需要任何单击处理程序,也不需要存储对它的任何引用。这看起来像这样: .
egui
if ui.button("Save file").clicked() { save(file); }
有关即时模式的更详细说明,请参阅 egui 文档
。
这两种系统都有优点和缺点。
简而言之:即时模式 GUI 库更易于使用,但功能不那么强大。
即时模式的主要优点是应用程序代码变得简单得多:
换句话说,大量的代码、复杂性和错误都消失了,你可以把时间集中在比编写GUI代码更有趣的事情上。
即时模式的主要缺点是它使布局更加困难。假设你想在屏幕中央显示一个小的对话窗口。要正确定位窗口,GUI 库必须首先知道窗口的大小。要知道窗口的大小,GUI 库必须首先布局窗口的内容。在保留模式下,这很容易:GUI 库执行窗口布局,定位窗口,然后检查交互(“是否单击了”确定“按钮?
在即时模式下,你会遇到一个悖论:要知道窗口的大小,我们必须进行布局,但布局代码还会检查交互(“是否单击了”确定“按钮?”),因此它需要在显示窗口内容之前知道窗口位置。这意味着我们必须在知道窗口大小之前决定在哪里显示窗口!
这是即时模式 GUI 的一个根本缺点,任何解决它的尝试都有其自身的缺点。
一种解决方法是存储大小并在下一帧使用它。这会为正确的布局产生帧延迟,偶尔会在显示第一帧时闪烁。 对某些内容(如窗口和网格布局)执行此操作。
egui
你也可以调用布局代码两次(一次是为了获取大小,一次是为了进行交互),但这不仅更昂贵,而且实现起来也很复杂,在某些情况下两次是不够的。 从不这样做。
egui
对于“原子”小部件(例如按钮)在显示之前就知道大小,因此可以在没有任何特殊解决方法的情况下居中按钮、标签等。
egui
egui
由于即时模式 GUI 每帧都会执行完整布局,因此布局代码需要快速。如果你有一个非常复杂的GUI,这可能会给CPU带来负担。特别是,在滚动区域中具有非常大的 UI(具有很长的回滚)可能会很慢,因为内容需要对每一帧进行布局。
如果你在设计 GUI 时考虑到这一点,并且避免使用巨大的滚动区域(或仅布置视图中的部分),那么性能影响通常很小。在大多数情况下,你可以期望每帧占用 1-2 毫秒,但仍有很大的优化空间(我还没有关注它)。你还可以设置为仅在有交互(例如鼠标移动)时重新绘制。
egui
egui
egui
如果你的 GUI 是高度交互的,那么与保留模式相比,即时模式实际上可能性能更高。转到任何网页并调整浏览器窗口的大小,你会注意到浏览器进行布局的速度非常慢,并且消耗了大量的 CPU。相比之下,调整窗口大小,你将获得流畅的 60 FPS,而无需额外的 CPU 成本。
egui
你希望 GUI 库保留某些 GUI 状态,即使在即时模式库(如 )中也是如此。这包括窗口的位置和大小以及用户在某些 UI 中滚动的距离。在这些情况下,你需要提供唯一标识符的种子(在父 UI 中唯一)。例如:默认情况下,使用窗口标题作为唯一 ID 来存储窗口位置。如果需要两个具有相同名称的窗口(或一个具有动态名称的窗口),则必须提供一些其他 ID 源(一些唯一的整数或字符串)。
egui
egui
egui
egui
egui还需要跟踪正在与哪个小部件交互(例如,正在拖动哪个滑块)。 对此井使用唯一的 id:s,但在这种情况下,ID 是自动生成的,因此用户无需担心。特别是,拥有两个同名按钮是没有问题的(这与
亲爱的ImGui
形成鲜明对比)。egui
总的来说,ID处理是一个罕见的不便,而不是一个很大的缺点。
另请参阅 GitHub 讨论。
egui
是的!但是你需要使用 安装自己的字体(或 )。
.ttf
.otf
Context::set_fonts
是的!你可以使用 自定义所有内容的颜色、间距、字体和大小。
Context::set_style
下面是一个示例(来自 https://github.com/AlexxxRu/TinyPomodoro):
async
如果你调用 GUI 代码,UI 将冻结,这是非常糟糕的用户体验。相反,请保持 GUI 线程无阻塞,并使用如下内容与任何并发任务(任务或其他线程)进行通信:
.await
async
mpsc::channel
)。确保使用try_recv
这样你就不会阻塞 gui 线程!Arc<Mutex<Value>>(后台线程设置一个值;GUI 线程读取它)
poll_promise::P romise
(例如:examples/download_image/
)eventuals::Eventual
tokio::sync::watch::channel
egui 包括对 AccessKit 的可选支持,该支持目前在 Windows 和 macOS 上实现了本机辅助功能 API。默认情况下,此功能在 eframe 中处于启用状态。对于 AccessKit 尚不支持的平台(包括 Web),有一个实验性的内置屏幕阅读器;在网络演示中,你可以在“后端”选项卡中启用它。
关于 egui 中可访问性的原始讨论在 https://github.com/emilk/egui/issues/167.现在,AccessKit 支持已合并,为未来的辅助功能工作奠定了坚实的基础,请针对特定的辅助功能问题打开新问题。
egui是一个 2D 用户界面库,用于布局按钮、滑块等并与之交互。 不知道它是在网络上运行还是在本地运行,也不知道如何收集输入或在屏幕上显示内容。这是集成或后端的工作。
egui
通常从游戏引擎使用(例如使用 bevy_egui
),但你也可以单独使用 . 集成了 Web 和本机,并处理输入和渲染。中的框架既代表你的 egui 应用程序所在的框架,也代表“框架”(是一个框架,是一个库)。
egui
egui
eframe
eframe
eframe
frame
egui
有多种方法可以将 egui 与 3D 相结合。最简单的方法是使用 3D 库并让 egui 位于 3D 视图的顶部。例如,请参阅bevy_egui
或三维
。
如果要将 3D 嵌入到 egui 视图中,有两个选项。
Shape::Callback
例子:
Shape::Callback将在绘制 EGUI 时调用你的代码,以使用任何背景渲染上下文显示任何内容。使用
eframe
时,这将发光。
其他集成将为你提供其他渲染上下文(如果它们支持的话)。Shape::Callback
你还可以将 3D 场景渲染为纹理并使用 ui.image(...)
显示它。你首先需要将原生纹理转换为 egui::TextureId
,如何执行此操作取决于你使用的集成。
例子:
egui-miniquad
: https://github.com/not-fl3/egui-miniquad/blob/master/examples/render_to_egui_image.rs
egui_glium
:https://github.com/emilk/egui/blob/master/crates/egui_glium/examples/native_texture.rs。所有坐标均采用屏幕空间坐标,左上角为 (0, 0)
所有坐标都在“点”中,这些“点”可能包含许多物理像素。
所有颜色都有预乘字母。
EGUI 将构建器模式用于构造小部件。例如:我不是构建器模式的忠实粉丝(它在实现和使用中都非常冗长),但在 Rust 命名之前,默认参数是我们能做的最好的事情。为了缓解一些冗长的问题,可以使用常见的帮助程序函数,例如 。
ui.add(Label::new("Hello").text_color(RED));
ui.label("Hello");
egui 不使用匹配样式函数调用(容易出错),而是更喜欢使用传递给包装函数的闭包。Lambdas有点丑,所以我想找到一个更好的解决方案。https://github.com/emilk/egui/issues/1004#issuecomment-1001650754 对此进行更多讨论。
begin/end
FnOnce
唯一的Dear ImGui是一个很棒的即时模式GUI,适用于C++,适用于许多后端。该库彻底改变了我对 GUI 代码的看法,并将 GUI 编程从我讨厌做的事情变成了我现在喜欢的事情。
图书馆和项目的名称是“egui”,发音为“e-gooey”。请不要将其写成“EGUI”。
该图书馆最初被称为“Emigui”,但在 2020 年更名为“egui”。
egui 作者和维护者:Emil Ernerfeldt (@emilk)。
值得注意的贡献:
egui_glow
。上下文重构
。egui 根据 MIT 或 Apache-2.0 获得许可。
默认字体:
emoji-icon-font.ttf: 版权所有 (c) 2014 约翰·斯莱格斯 , MIT 许可证
Hack-Regular.ttf: https://github.com/source-foundry/Hack, MIT 授权协议
NotoEmoji-Regular.ttf: google.com/get/noto, SIL 开放字体许可证
Ubuntu-Light.ttf作者:Dalton Maag:Ubuntu字体许可证
egui 开发由 Rerun 赞助,Rerun 是一家为计算机视觉和机器人技术提供
可视化的初创公司。