Back to Blog

egui Floating Windows & Dialogs | Rust GUI Ep 22

Sandy LaneSandy Lane

Video: egui Floating Windows & Dialogs | Rust GUI Ep 22 by Taught by Celeste AI - AI Coding Coach

Watch full page →

egui Floating Windows & Dialogs in Rust GUI

Learn how to create floating windows and confirmation dialogs in egui by building a simple Post Manager app. This tutorial covers using egui::Window::new() to spawn windows, controlling their visibility with .open(), customizing behavior with .resizable() and .collapsible(), and centering dialogs using .anchor(Align2::CENTER_CENTER).

Code

use eframe::egui::{self, Align2};

struct Post {
  title: String,
  body: String,
}

struct MyApp {
  posts: Vec<Post>,
  show_new_post: bool,
  show_about: bool,
  confirm_delete: Option<usize>, // index of post to delete
}

impl Default for MyApp {
  fn default() -> Self {
    Self {
      posts: vec![
        Post { title: "Hello".into(), body: "This is the first post.".into() },
        Post { title: "Second Post".into(), body: "More content here.".into() },
      ],
      show_new_post: false,
      show_about: false,
      confirm_delete: None,
    }
  }
}

impl eframe::App for MyApp {
  fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
    // Top toolbar with buttons
    egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
      if ui.button("New Post").clicked() {
        self.show_new_post = true;
      }
      ui.separator();
      if ui.button("About").clicked() {
        self.show_about = true;
      }
    });

    // Central panel listing posts
    egui::CentralPanel::default().show(ctx, |ui| {
      for (i, post) in self.posts.iter().enumerate() {
        ui.horizontal(|ui| {
          ui.label(&post.title);
          if ui.button("View").clicked() {
            // Open a floating window for this post
            // We'll track open state by a bool per post if needed
          }
          if ui.button("Delete").clicked() {
            self.confirm_delete = Some(i);
          }
        });
      }
    });

    // Floating windows for each post (simplified)
    for post in &self.posts {
      egui::Window::new(&post.title)
        .resizable(true)
        .collapsible(true)
        .show(ctx, |ui| {
          ui.label(&post.body);
        });
    }

    // New post window
    egui::Window::new("New Post")
      .open(&mut self.show_new_post)
      .resizable(false)
      .show(ctx, |ui| {
        static mut NEW_TITLE: String = String::new();
        static mut NEW_BODY: String = String::new();

        // Safety: simplified example; in real code, store in struct fields
        unsafe {
          ui.label("Title:");
          ui.text_edit_singleline(&mut NEW_TITLE);
          ui.label("Body:");
          ui.text_edit_multiline(&mut NEW_BODY);

          if ui.button("Publish").clicked() {
            self.posts.push(Post {
              title: NEW_TITLE.clone(),
              body: NEW_BODY.clone(),
            });
            NEW_TITLE.clear();
            NEW_BODY.clear();
            self.show_new_post = false;
          }
        }
      });

    // Confirm delete dialog centered
    if let Some(i) = self.confirm_delete {
      egui::Window::new("Confirm Delete")
        .open(&mut self.confirm_delete.is_some())
        .anchor(Align2::CENTER_CENTER, egui::Vec2::ZERO)
        .resizable(false)
        .collapsible(false)
        .show(ctx, |ui| {
          ui.label(format!("Delete post \"{}\"?", self.posts[i].title));
          ui.horizontal(|ui| {
            if ui.button("Delete").clicked() {
              self.posts.remove(i);
              self.confirm_delete = None;
            }
            if ui.button("Cancel").clicked() {
              self.confirm_delete = None;
            }
          });
        });
    }

    // About window
    egui::Window::new("About")
      .open(&mut self.show_about)
      .resizable(false)
      .show(ctx, |ui| {
        ui.label("Post Manager built with egui and eframe.");
      });
  }
}

Key Points

  • egui::Window::new() creates floating windows that can be customized.
  • The .open(&mut bool) method toggles window visibility based on a mutable boolean.
  • .resizable() and .collapsible() control whether the window can be resized or collapsed.
  • .anchor(Align2::CENTER_CENTER) positions windows or dialogs centered on the screen.
  • Use floating windows for editing/viewing posts and confirmation dialogs to improve UI flow.