I finally cracked the code for EGUI button centering! When I wanted to have difficulty selection buttons neatly lined up in the center, I ran into some tricky immediate mode GUI challenges. Let me walk you through how I solved puzzle.
Understanding EGUI’s Immediate Mode GUI
EGUI is an immediate mode GUI library. This means that EGUI draws the GUI every frame and doesn’t retain any state. So when you want to do any changes to the GUI, you need to keep your own state and define the full GUI every frame again. Same for click or hover events, you can define the response immediately inline.
Immediate mode GUIs are particularly popular in game development, aligning well with the frame-based rendering approach most games use.
Advantages of Immediate Mode GUIs
- Simplified State Management: No need to manually track GUI state, as the interface redraws every frame
- Declarative Coding: The frame-by-frame redraw enables more straightforward, declarative code structures
- Inline Event Handling: The code for drawing the GUI and handling events are in the same place, allowing easier interaction without tracking individual GUI elements
Challenges with Immediate Mode GUIs
- Precise Positioning Difficulties: Determining exact element coordinates can be tricky when drawing in real-time as your code and layout can influence the size of elements, while you also want to determine if a button was clicked in the same time
- Performance Considerations: Redrawing the entire GUI every frame can introduce CPU overhead
EGUI decided to limit the layout possibilities to deal with the precise positioning difficulties, leading to difficulties drawing centralised elements.
My Trick for Perfect EGUI Button Centering
To centralize my difficulty selection buttons I used the following approach:
- Calculate the exact width of the elements that need to be centralised
- Create a container with a fixed width based on this calculation
- Center and justify this container
Here is the Rust code:
fn build(&mut self, ui: &mut egui::Ui, commands: &mut Commands) {
let layout = egui::Layout::centered_and_justified(egui::Direction::LeftToRight);
ui.allocate_ui_with_layout(
[(self.options.len() as f32 + 1.) * 205., 50.].into(),
layout,
|ui| {
ui.horizontal(|ui| {
ui.add_sized(
[200., 50.],
egui::Label::new(egui::RichText::new(&self.label).size(24.).color(egui::Color32::WHITE))
);
for option in &mut self.options {
option.render(ui, commands);
}
});
});
ui.add_space(20.);
}
What’s next
My next development goal is to create a control selection screen where you can decide which buttons to use to move the paddle. Stay tuned for updates on this blog!

Leave a Reply