egui README

The project's README from github.com/emilk/egui. As one markdown file: README.md.

🖌 egui: an easy-to-use GUI in pure Rust

github Latest version Documentation unsafe forbidden Build Status MIT Apache Discord



👉 Click to run the web demo 👈

egui (pronounced "e-gooey") is a simple, fast, and highly portable immediate mode GUI library for Rust. egui runs on the web, natively, and in your favorite game engine.

egui aims to be the easiest-to-use Rust GUI library, and the simplest way to make a web app in Rust.

egui can be used anywhere you can draw textured triangles, which means you can easily integrate it into your game engine of choice.

eframe is the official egui framework, which supports writing apps for Web, Linux, Mac, Windows, and Android.

Example

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("Increment").clicked() {
    age += 1;
}
ui.label(format!("Hello '{name}', age {age}"));
ui.image(egui::include_image!("ferris.png"));

Dark mode     Light mode

Sections:

(egui 的中文翻译文档 / chinese translation)

Quick start

There are simple examples in the examples/ folder. If you want to write a web app, then go to https://github.com/emilk/eframe_template/ and follow the instructions. The official docs are at https://docs.rs/egui. For inspiration and more examples, check out the egui web demo and follow the links in it to its source code.

If you want to integrate egui into an existing engine, go to the Integrations section.

If you have questions, use GitHub Discussions. There is also an egui discord server. If you want to contribute to egui, please read the Contributing Guidelines.

Demo

Click to run egui web demo (works in any browser with Wasm and WebGL support). Uses eframe.

To test the demo app locally, run cargo run --release -p egui_demo_app.

The native backend is egui-wgpu (using wgpu) and should work out-of-the-box on Mac and Windows, but on Linux you need to first run:

sudo apt-get install -y libclang-dev libgtk-3-dev libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev libxkbcommon-dev libssl-dev

On Fedora Rawhide you need to run:

dnf install clang clang-devel clang-tools-extra libxkbcommon-devel pkg-config openssl-devel libxcb-devel gtk3-devel atk fontconfig-devel

NOTE: This is just for the demo app - egui itself is completely platform agnostic!

Goals

egui is not a framework. egui is a library you call into, not an environment you program for.

NOTE: egui does not claim to have reached all these goals yet! egui is still work in progress.

Non-goals

State

egui is in active development. It works well for what it does, but it lacks many features and the interfaces are still in flux. New releases will have breaking changes.

Still, egui can be used to create professional looking applications, like the Rerun Viewer.

Features

Check out the 3rd party egui crates wiki for even more widgets and features, maintained by the community.

Light Theme:

Dependencies

egui has a minimal set of default dependencies. Heavier dependencies are kept out of egui, even as opt-in. All code in egui is Wasm-friendly (even outside a browser).

To load images into egui you can use the official egui_extras crate.

eframe on the other hand has a lot of dependencies, including winit, image, graphics crates, clipboard crates, etc,

Who is egui for?

egui aims to be the best choice when you want a simple way to create a GUI, or you want to add a GUI to a game engine.

If you are not using Rust, egui is not for you. If you want a GUI that looks native, egui is not for you. If you want something that doesn't break when you upgrade it, egui isn't for you (yet).

But if you are writing something interactive in Rust that needs a simple GUI, egui may be for you.

Integrations

egui is built to be easy to integrate into any existing game engine or platform you are working on. egui itself doesn't know or care on what OS it is running or how to render things to the screen - that is the job of the egui integration.

An integration needs to do the following each frame:

Official integrations

These are the official egui integrations:

3rd party integrations

Check the wiki to find 3rd party integrations and egui crates.

Writing your own egui integration

Missing an integration for the thing you're working on? Create one, it's easy! See https://docs.rs/egui/latest/egui/#integrating-with-egui.

Why immediate mode

egui is an immediate mode GUI library, as opposed to a retained mode GUI library. The difference between retained mode and immediate mode is best illustrated with the example of a button: In a retained GUI you create a button, add it to some UI and install some on-click handler (callback). The button is retained in the UI, and to change the text on it you need to store some sort of reference to it. By contrast, in immediate mode you show the button and interact with it immediately, and you do so every frame (e.g. 60 times per second). This means there is no need for any on-click handler, nor to store any reference to it. In egui this looks like this: if ui.button("Save file").clicked() { save(file); }.

A more detailed description of immediate mode can be found in the egui docs.

There are advantages and disadvantages to both systems.

The short of it is this: immediate mode GUI libraries are easier to use, but less powerful.

Advantages of immediate mode

Usability

The main advantage of immediate mode is that the application code becomes vastly simpler:

In other words, a whole lot of code, complexity and bugs are gone, and you can focus your time on something more interesting than writing GUI code.

Disadvantages of immediate mode

Layout

The main disadvantage of immediate mode is it makes layout more difficult. Say you want to show a small dialog window in the center of the screen. To position the window correctly the GUI library must first know the size of it. To know the size of the window the GUI library must first layout the contents of the window. In retained mode this is easy: the GUI library does the window layout, positions the window, then checks for interaction ("was the OK button clicked?").

In immediate mode you run into a paradox: to know the size of the window, we must do the layout, but the layout code also checks for interaction ("was the OK button clicked?") and so it needs to know the window position before showing the window contents. This means we must decide where to show the window before we know its size!

This is a fundamental shortcoming of immediate mode GUIs, and any attempt to resolve it comes with its own downsides.

One workaround is to store the size and use it the next frame. This produces a frame-delay for the correct layout, producing occasional flickering the first frame something shows up. egui does this for some things such as windows and grid layouts.

The "first-frame jitter" can be covered up with an extra pass, which egui supports via Context::request_discard. The downside of this is the added CPU cost of a second pass, so egui only does this in very rare circumstances (the majority of frames are single-pass).

For "atomic" widgets (e.g. a button) egui knows the size before showing it, so centering buttons, labels etc is possible in egui without any special workarounds.

See this issue for more.

CPU usage

Since an immediate mode GUI does a full layout each frame, the layout code needs to be quick. If you have a very complex GUI this can tax the CPU. In particular, having a very large UI in a scroll area (with very long scrollback) can be slow, as the content needs to be laid out each frame.

If you design the GUI with this in mind and refrain from huge scroll areas (or only lay out the part that is in view) then the performance hit is generally pretty small. For most cases you can expect egui to take up 1-2 ms per frame, but egui still has a lot of room for optimization (it's not something I've focused on yet). egui only repaints when there is interaction (e.g. mouse movement) or an animation, so if your app is idle, no CPU is wasted.

If your GUI is highly interactive, then immediate mode may actually be more performant compared to retained mode. Go to any web page and resize the browser window, and you'll notice that the browser is very slow to do the layout and eats a lot of CPU doing it. Resize a window in egui by contrast, and you'll get smooth 60 FPS at no extra CPU cost.

IDs

There are some GUI state that you want the GUI library to retain, even in an immediate mode library such as egui. This includes position and sizes of windows and how far the user has scrolled in some UI. In these cases you need to provide egui with a seed of a unique identifier (unique within the parent UI). For instance: by default egui uses the window titles as unique IDs to store window positions. If you want two windows with the same name (or one window with a dynamic name) you must provide some other ID source to egui (some unique integer or string).

egui also needs to track which widget is being interacted with (e.g. which slider is being dragged). egui uses unique IDs for this as well, but in this case the IDs are automatically generated, so there is no need for the user to worry about it. In particular, having two buttons with the same name is no problem (this is in contrast with Dear ImGui).

Overall, ID handling is a rare inconvenience, and not a big disadvantage.

FAQ

Also see GitHub Discussions.

Can I use egui with non-latin characters?

Yes! But you need to install your own font (.ttf or .otf) using Context::set_fonts.

Can I customize the look of egui?

Yes! You can customize the colors, spacing, fonts and sizes of everything using Context::set_style.

This is not yet as powerful as say CSS, but this is going to improve.

Here is an example (from https://github.com/a-liashenko/TinyPomodoro):

How do I use egui with async?

If you call .await in your GUI code, the UI will freeze, which is very bad UX. Instead, keep the GUI thread non-blocking and communicate with any concurrent tasks (async tasks or other threads) with something like:

How do I create a file dialog?

The async version of rfd supports both native and Wasm. See example app here https://github.com/woelper/egui_pick_file which also has a demo available via gitub pages.

What about accessibility, such as screen readers?

egui includes optional support for AccessKit, which currently implements the native accessibility APIs on Windows and macOS. This feature is enabled by default in eframe. For platforms that AccessKit doesn't yet support, including web, there is an experimental built-in screen reader; in the web demo you can enable it in the "Backend" tab.

See the accessibility guide for how labels, custom widgets, AccessKit, and egui_kittest fit together.

The original discussion of accessibility in egui is at https://github.com/emilk/egui/issues/167. Now that AccessKit support is merged, providing a strong foundation for future accessibility work, please open new issues on specific accessibility problems.

What is the difference between egui and eframe?

egui is a 2D user interface library for laying out and interacting with buttons, sliders, etc. egui has no idea if it is running on the web or natively, and does not know how to collect input or show things on screen. That is the job of the integration or backend.

It is common to use egui from a game engine (using e.g. bevy_egui), but you can also use egui stand-alone using eframe. eframe has integration for web and native, and handles input and rendering. The frame in eframe stands both for the frame in which your egui app resides and also for "framework" (eframe is a framework, egui is a library).

How do I render 3D stuff in an egui area?

There are multiple ways to combine egui with 3D. The simplest way is to use a 3D library and have egui sit on top of the 3D view. See for instance bevy_egui or three-d.

If you want to embed 3D into an egui view there are two options:

Shape::Callback

Example:

Shape::Callback will call your code when egui gets painted, to show anything using whatever the background rendering context is. When using eframe this will be glow. Other integrations will give you other rendering contexts, if they support Shape::Callback at all.

Render-to-texture

You can also render your 3D scene to a texture and display it using ui.image(…). You first need to convert the native texture to an [egui::TextureId](https://docs.rs/egui/latest/egui/

egui (emilk/egui)

Searching Database…

31.6K ·GitHub
这是什么?egui(读作 'e-gooey')是一个用纯 Rust 编写的简单、快速、可移植性极高的即时模式 GUI 库。它可以在网页上运行,可以在桌面端原生运行,也可以嵌入游戏引擎中。
egui 是库还是框架?eframe 又是什么?egui 是一个 2D UI 库——提供按钮、滑块、布局之类的控件,但它完全不了解窗口、输入和渲染。eframe 是官方的框架,补齐了这些功能,因此同一个应用既能编译成网页版,也能编译成本地版。
我怎么才能把应用跑起来?从仓库 examples/ 文件夹里的简单示例入手;如果你想写网页应用,快速上手文档会指向一个专门的模板。
它会不会给我的项目拖进一大堆依赖?egui 本身默认的依赖非常精简——较重的依赖不会被打包进来,连作为可选项加入都不行。eframe 正好相反:它会引入 winit、image、图形和剪贴板相关的 crate。
有哪些主要的坑需要提前知道?界面不是原生外观,而且 README 也承认升级版本时仍可能破坏你的代码(目前如此)。另外,在 GUI 代码里调用 .await 会卡死界面,所以异步任务必须放到 GUI 线程之外。
我的应用到底能在哪些平台上运行?使用 eframe 时,同一个应用既能编译成网页/wasm 版,也能编译成 Linux、Mac、Windows 和 Android 的本地应用。egui 还可以嵌入任何游戏引擎——只要能绘制带纹理的三角形,它就能用。
我能在自己的游戏引擎里用它吗?可以——只要能绘制带纹理的三角形,egui 就能运行。官方集成支持 glow 和 wgpu 渲染,以及用于窗口管理的 winit;wiki 上还列出了第三方集成,比如 Bevy 的。
怎么做异步处理才不会卡住界面?保持 GUI 线程不阻塞,通过 channel(使用 try_recv)、共享的 Arc 值,或 poll-promise、eventuals 这类 crate 与后台任务通信——千万不要在 GUI 代码里用 .await。
能在 egui 界面里混入 3D 内容吗?可以。最简单的做法是用另一个库渲染 3D,再把 egui 叠在上面(例如 Bevy 或 three-d)。如果想在 egui 视图内部嵌入 3D,可以用 Shape::Callback,或者把场景渲染成纹理,再用 ui.image 显示出来。
我的应用能配合屏幕阅读器使用吗?可以,但属于可选项:egui 支持 AccessKit,它在 Windows 和 macOS 上实现了原生的无障碍 API,并且在 eframe 中默认开启。在 AccessKit 尚不支持的平台(比如网页端),有一个实验性的内置屏幕阅读器。
What are similar projects?imgui, bgfx, raylib, iw4L, ebiten, crosstl, libgdx, benilla
Creator
emilk
Size
94.6 MB
Stars
31.6K
Age
7y
Commits · 90 Days