egui
egui: an easy-to-use immediate mode GUI in Rust that runs on both web and native
Top Related Projects
A cross-platform GUI library for Rust, inspired by Elm
Rust bindings for Dear ImGui
An opinionated 2D game engine for Rust
The Rust UI-Toolkit.
Rust bindings for the FLTK GUI library.
Slint is a declarative GUI toolkit to build native user interfaces for Rust, C++, or JavaScript apps.
Quick Overview
Egui is a simple, fast, and highly customizable immediate mode GUI library for Rust. It is designed to be easy to use and integrate into existing projects, and provides a wide range of features for building desktop, web, and mobile applications.
Pros
- Simple and Intuitive API: Egui has a straightforward and easy-to-use API, making it accessible for developers of all skill levels.
- High Performance: Egui is designed to be fast and efficient, with a focus on minimizing resource usage and maximizing responsiveness.
- Cross-Platform Compatibility: Egui supports a wide range of platforms, including desktop, web, and mobile, making it a versatile choice for developers.
- Highly Customizable: Egui provides a high degree of customization, allowing developers to create unique and visually appealing user interfaces.
Cons
- Limited Documentation: While the Egui project has a growing community, the documentation could be more comprehensive, especially for newer users.
- Steep Learning Curve: Egui's immediate mode GUI approach may be unfamiliar to developers who are more accustomed to traditional GUI frameworks, which can make the initial learning curve steeper.
- Dependency on Rust: Egui is a Rust-based library, which may be a barrier for developers who are not familiar with the Rust programming language.
- Lack of Third-Party Widgets: Compared to some other GUI frameworks, Egui has a relatively limited set of pre-built widgets, which may require more custom development.
Code Examples
Here are a few code examples demonstrating the usage of Egui:
- Creating a Simple Window:
egui::Window::new("My Window").show(ctx, |ui| {
ui.label("Hello, world!");
});
- Adding Interactivity:
let mut count = 0;
egui::Window::new("Clickable Window").show(ctx, |ui| {
ui.label(format!("You clicked the button {} times.", count));
if ui.button("Click me!").clicked() {
count += 1;
}
});
- Customizing the Appearance:
let mut color = egui::Color32::from_rgb(255, 0, 0);
egui::Window::new("Colored Window").show(ctx, |ui| {
ui.color_edit_button_srgb(&mut color);
ui.label(format!("The current color is {:?}", color));
});
- Integrating with External Libraries:
let image = egui::TextureId::from(my_custom_image_texture);
egui::Window::new("Image Window").show(ctx, |ui| {
ui.image(image, egui::vec2(200.0, 200.0));
});
Getting Started
To get started with Egui, you can follow these steps:
- Add the Egui dependency to your Cargo.toml file:
[dependencies]
egui = "0.19.0"
- Create a new Rust project and import the necessary Egui modules:
use egui::{Context, CentralPanel, Window};
- Initialize the Egui context and set up the main loop:
fn main() {
let options = eframe::NativeOptions::default();
eframe::run_native(
"My Egui App",
options,
Box::new(|cc| Box::new(MyApp::new(cc))),
);
}
struct MyApp {}
impl MyApp {
fn new(_cc: &eframe::CreationContext<'_>) -> Self {
Self {}
}
fn update(&mut self, ctx: &Context, _frame: &mut eframe::Frame) {
CentralPanel::default().show(ctx, |ui| {
ui.heading("Hello, Egui!");
ui.label("This is a simple Egui application.");
});
}
}
- Run your application using
cargo run
, and you should see a window
Competitor Comparisons
A cross-platform GUI library for Rust, inspired by Elm
Pros of iced
- Native look and feel across platforms
- Built-in support for responsive layouts
- More comprehensive widget set out-of-the-box
Cons of iced
- Steeper learning curve due to more complex architecture
- Slower compilation times and larger binary sizes
- Less flexible for custom rendering and immediate mode-style usage
Code Comparison
iced example:
use iced::{button, Button, Column, Element, Sandbox, Settings, Text};
struct Counter {
value: i32,
increment_button: button::State,
decrement_button: button::State,
}
impl Sandbox for Counter {
// ... implementation details
}
egui example:
use egui::Context;
fn ui(ctx: &Context) {
egui::CentralPanel::default().show(ctx, |ui| {
ui.heading("My egui Application");
if ui.button("Click me").clicked() {
// Handle click
}
});
}
iced focuses on a more traditional retained-mode GUI approach with a declarative style, while egui emphasizes immediate mode rendering and a more imperative programming style. iced provides a more structured framework for building complex applications, whereas egui offers simplicity and flexibility for rapid prototyping and integration into existing projects.
Rust bindings for Dear ImGui
Pros of imgui-rs
- Bindings to the popular C++ Dear ImGui library, benefiting from its maturity and extensive features
- Wider ecosystem and community support due to its longer existence
- More comprehensive documentation and examples
Cons of imgui-rs
- Requires linking to C++ code, which can complicate build processes
- Less idiomatic Rust API due to being a wrapper around C++ code
- Potentially higher memory usage and slower performance due to FFI overhead
Code Comparison
imgui-rs:
ui.window("Hello")
.size([300.0, 100.0], Condition::FirstUseEver)
.build(|| {
ui.text("Hello world!");
ui.button("Save");
});
egui:
egui::Window::new("Hello").show(ctx, |ui| {
ui.label("Hello world!");
if ui.button("Save").clicked() {
// Handle click
}
});
Summary
imgui-rs provides bindings to a mature C++ library with extensive features and community support. However, it may have more complex build processes and less idiomatic Rust code. egui, being a pure Rust implementation, offers a more native Rust experience but may have fewer features compared to the well-established Dear ImGui library.
An opinionated 2D game engine for Rust
Pros of Coffee
- Focuses on 2D game development, providing specialized features for game creation
- Offers a simple and intuitive API for handling game loops and input
- Includes built-in support for audio playback and sound effects
Cons of Coffee
- Less flexible for general-purpose GUI applications compared to egui
- Smaller community and fewer resources available for learning and troubleshooting
- Limited to 2D graphics, while egui supports both 2D and 3D rendering
Code Comparison
Coffee example:
use coffee::graphics::{Color, Frame, Window, WindowSettings};
use coffee::load::Task;
use coffee::{Game, Timer};
struct MyGame;
impl Game for MyGame {
fn update(&mut self, _window: &Window) {}
fn draw(&mut self, frame: &mut Frame, _timer: &Timer) {
frame.clear(Color::BLACK);
}
}
egui example:
use eframe::egui;
fn main() -> Result<(), eframe::Error> {
let options = eframe::NativeOptions::default();
eframe::run_native(
"My egui App",
options,
Box::new(|_cc| Box::new(MyApp::default())),
)
}
struct MyApp {}
impl eframe::App for MyApp {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
egui::CentralPanel::default().show(ctx, |ui| {
ui.label("Hello World!");
});
}
}
The Rust UI-Toolkit.
Pros of OrbTK
- Cross-platform support for desktop, web, and mobile
- More comprehensive widget set out-of-the-box
- Integrated theming system for consistent look and feel
Cons of OrbTK
- Less active development and community support
- Steeper learning curve due to more complex architecture
- Larger binary size and potentially slower performance
Code Comparison
OrbTK example:
use orbtk::prelude::*;
fn main() {
Application::new()
.window(|ctx| {
Window::new()
.title("OrbTK")
.child(TextBlock::new().text("Hello, OrbTK!"))
.build(ctx)
})
.run();
}
egui example:
use eframe::egui;
fn main() -> Result<(), eframe::Error> {
eframe::run_native(
"egui",
eframe::NativeOptions::default(),
Box::new(|_cc| Box::new(MyApp::default())),
)
}
struct MyApp;
impl eframe::App for MyApp {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
egui::CentralPanel::default().show(ctx, |ui| {
ui.label("Hello, egui!");
});
}
}
Both libraries offer Rust-based GUI development, but egui focuses on immediate mode rendering and simplicity, while OrbTK provides a more traditional retained mode approach with a richer widget set. egui tends to be lighter and faster, making it suitable for performance-critical applications, while OrbTK offers more built-in features for complex UIs across multiple platforms.
Rust bindings for the FLTK GUI library.
Pros of fltk-rs
- Native look and feel across platforms
- Extensive widget set for complex GUI applications
- Mature and stable, with a long history in C++
Cons of fltk-rs
- Larger binary size due to comprehensive widget set
- Steeper learning curve for beginners
- Less modern, flat design aesthetics
Code Comparison
fltk-rs example:
use fltk::{app, button::Button, frame::Frame, prelude::*, window::Window};
fn main() {
let app = app::App::default();
let mut wind = Window::new(100, 100, 400, 300, "Hello from rust");
let mut frame = Frame::new(0, 0, 400, 200, "");
let mut but = Button::new(160, 210, 80, 40, "Click me!");
wind.end();
wind.show();
but.set_callback(move |_| frame.set_label("Hello World!"));
app.run().unwrap();
}
egui example:
use eframe::egui;
fn main() {
let options = eframe::NativeOptions::default();
eframe::run_native(
"My egui App",
options,
Box::new(|_cc| Box::new(MyApp::default())),
);
}
struct MyApp {
name: String,
}
impl Default for MyApp {
fn default() -> Self {
Self {
name: "Arthur".to_owned(),
}
}
}
impl eframe::App for MyApp {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
egui::CentralPanel::default().show(ctx, |ui| {
ui.heading("My egui Application");
ui.horizontal(|ui| {
ui.label("Your name: ");
ui.text_edit_singleline(&mut self.name);
});
ui.label(format!("Hello {}!", self.name));
});
}
}
Slint is a declarative GUI toolkit to build native user interfaces for Rust, C++, or JavaScript apps.
Pros of Slint
- Multi-language support: Slint can be used with Rust, C++, and JavaScript
- Declarative UI design with a custom markup language
- Built-in support for responsive layouts and animations
Cons of Slint
- Steeper learning curve due to custom markup language
- Less mature ecosystem compared to egui
- Potentially higher resource usage for complex UIs
Code Comparison
Slint example:
export component Button {
width: 100px;
height: 30px;
Text {
text: "Click me";
color: black;
}
}
egui example:
ui.add(egui::Button::new("Click me").min_size(Vec2::new(100.0, 30.0)));
Slint uses a custom markup language for UI definition, while egui uses Rust code directly. Slint's approach may be more intuitive for designers, but egui's integration with Rust can be more natural for developers already familiar with the language.
Both libraries aim to provide efficient and easy-to-use GUI solutions for Rust, but they take different approaches. Slint offers a more traditional GUI framework experience with its markup language and multi-language support, while egui focuses on immediate mode rendering and tight integration with Rust.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
ð egui: an easy-to-use GUI in pure Rust
egui development is sponsored by Rerun, a startup building
an SDK for visualizing streams of multimodal data.
ð 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"));
Sections:
- Example
- Quick start
- Demo
- Goals
- State / features
- Dependencies
- Who is egui for?
- Integrations
- Why immediate mode
- FAQ
- Other
- Credits
(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 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_glow
(using glow
) 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
- The easiest to use GUI library
- Responsive: target 60 Hz in debug build
- Friendly: difficult to make mistakes, and shouldn't panic
- Portable: the same code works on the web and as a native app
- Easy to integrate into any environment
- A simple 2D graphics API for custom painting (
epaint
). - No callbacks
- Pure immediate mode
- Extensible: easy to write your own widgets for egui
- Modular: You should be able to use small parts of egui and combine them in new ways
- Safe: there is no
unsafe
code in egui - Minimal dependencies
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
- Become the most powerful GUI library
- Native looking interface
- Advanced and flexible layouts (that's fundamentally incompatible with immediate mode)
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
- Widgets: label, text button, hyperlink, checkbox, radio button, slider, draggable value, text editing, color picker, spinner
- Images
- Layouts: horizontal, vertical, columns, automatic wrapping
- Text editing: multiline, copy/paste, undo, emoji supports
- Windows: move, resize, name, minimize and close. Automatically sized and positioned.
- Regions: resizing, vertical scrolling, collapsing headers (sections), panels
- Rendering: Anti-aliased rendering of lines, circles, text and convex polygons.
- Tooltips on hover
- Accessibility via AccessKit
- Label text selection
- And more!
Light Theme:
Dependencies
egui
has a minimal set of default dependencies:
Heavier dependencies are kept out of egui
, even as opt-in.
No code that isn't fully Wasm-friendly is part of egui
.
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:
- Input: Gather input (mouse, touches, keyboard, screen size, etc) and give it to egui
- Call into the application GUI code
- Output: Handle egui output (cursor changes, paste, texture allocations, â¦)
- Painting: Render the triangle mesh egui produces (see OpenGL example)
Official integrations
These are the official egui integrations:
eframe
for compiling the same app to web/wasm and desktop/native. Usesegui-winit
andegui_glow
oregui-wgpu
egui_glow
for rendering egui with glow on native and web, and for making native appsegui-wgpu
for wgpu (WebGPU API)egui-winit
for integrating with winit
3rd party integrations
egui-ash
forash
(a very lightweight wrapper around Vulkan)bevy_egui
for the Bevy game engineegui_gl_glfw
for GLFWegui_glium
for compiling native apps with Gliumegui-glutin-gl
for glutinegui_sdl2_gl
for SDL2egui_sdl2_platform
for SDL2egui_vulkano
for Vulkanoegui_winit_vulkano
for Vulkanoegui-macroquad
for macroquadegui-miniquad
for Miniquadegui_speedy2d
for Speedy2degui-tetra2
for Tetra, a 2D game frameworkegui-winit-ash-integration
for winit and ashfltk-egui
for fltk-rsggegui
for the ggez game frameworkgodot-egui
for godot-rustnannou_egui
for nannounotan_egui
for notanscreen-13-egui
for Screen 13egui_skia
for skiasmithay-egui
for smithaytauri-egui
for tauri
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:
- You never need to have any on-click handlers and callbacks that disrupts your code flow.
- You don't have to worry about a lingering callback calling something that is gone.
- Your GUI code can easily live in a simple function (no need for an object just for the UI).
- You don't have to worry about app state and GUI state being out-of-sync (i.e. the GUI showing something outdated), because the GUI isn't storing any state - it is showing the latest state immediately.
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.
You can also call the layout code twice (once to get the size, once to do the interaction), but that is not only more expensive, it's also complex to implement, and in some cases twice is not enough. egui
never does this.
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:
- Channels (e.g.
std::sync::mpsc::channel
). Make sure to usetry_recv
so you don't block the gui thread! Arc<Mutex<Value>>
(background thread sets a value; GUI thread reads it)poll_promise::Promise
eventuals::Eventual
tokio::sync::watch::channel
How to 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.
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
, and how to do this depends on the integration you use.
Examples:
- Using
egui-miniquad
: https://github.com/not-fl3/egui-miniquad/blob/master/examples/render_to_egui_image.rs
Other
Conventions and design choices
All coordinates are in screen space coordinates, with (0, 0) in the top left corner
All coordinates are in logical "points" which may consist of many physical pixels.
All colors have premultiplied alpha, unless otherwise stated.
egui uses the builder pattern for construction widgets. For instance: ui.add(Label::new("Hello").text_color(RED));
I am not a big fan of the builder pattern (it is quite verbose both in implementation and in use) but until Rust has named, default arguments it is the best we can do. To alleviate some of the verbosity there are common-case helper functions, like ui.label("Hello");
.
Instead of using matching begin/end
style function calls (which can be error prone) egui prefers to use FnOnce
closures passed to a wrapping function. Lambdas are a bit ugly though, so I'd like to find a nicer solution to this. More discussion of this at https://github.com/emilk/egui/issues/1004#issuecomment-1001650754.
egui uses a single RwLock
for short-time locks on each access of Context
data. This is to leave implementation simple and transactional and allow users to run their UI logic in parallel. Instead of creating mutex guards, egui uses closures passed to a wrapping function, e.g. ctx.input(|i| i.key_down(Key::A))
. This is to make it less likely that a user would accidentally double-lock the Context
, which would lead to a deadlock.
Inspiration
The one and only Dear ImGui is a great Immediate Mode GUI for C++ which works with many backends. That library revolutionized how I think about GUI code and turned GUI programming from something I hated to do to something I now enjoy.
Name
The name of the library and the project is "egui" and pronounced as "e-gooey". Please don't write it as "EGUI".
The library was originally called "Emigui", but was renamed to "egui" in 2020.
Credits
egui author and maintainer: Emil Ernerfeldt (@emilk).
Notable contributions by:
- @n2: Mobile web input and IME support
- @optozorax: Arbitrary widget data storage
- @quadruple-output: Multitouch
- @EmbersArc: Plots
- @AsmPrgmC3: Proper sRGBA blending for web
- @AlexApps99:
egui_glow
- @mankinskin: Context menus
- @t18b219k: Port glow painter to web
- @danielkeller:
Context
refactor - @MaximOsipenko:
Context
lock refactor - @mwcampbell: AccessKit integration
- @hasenbanck, @s-nie, @Wumpf:
egui-wgpu
- @jprochazk: egui image API
- And many more.
egui is licensed under MIT OR Apache-2.0.
- The flattening algorithm for the cubic bezier curve and quadratic bezier curve is from lyon_geom
Default fonts:
emoji-icon-font.ttf
: Copyright (c) 2014 John Slegers , MIT LicenseHack-Regular.ttf
: https://github.com/source-foundry/Hack, MIT LicenceNotoEmoji-Regular.ttf
: google.com/get/noto, SIL Open Font LicenseUbuntu-Light.ttf
by Dalton Maag: Ubuntu font licence
egui development is sponsored by Rerun, a startup building
an SDK for visualizing streams of multimodal data.
Top Related Projects
A cross-platform GUI library for Rust, inspired by Elm
Rust bindings for Dear ImGui
An opinionated 2D game engine for Rust
The Rust UI-Toolkit.
Rust bindings for the FLTK GUI library.
Slint is a declarative GUI toolkit to build native user interfaces for Rust, C++, or JavaScript apps.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot