I'm trying to create remove folder button in my app. But ui.button(text).clicked isn't working in a for loop. "Remove" buttons are in each folder.
use eframe::{App, egui, Frame, NativeOptions, run_native};
use eframe::egui::{CentralPanel, Color32, Context, SidePanel, Visuals};
use crate::egui::RichText;
struct MyApp { add_folder_string: Vec<String>, folders: Vec<String> }
impl MyApp {
fn new(cc: &eframe::CreationContext<'_>) -> Self {
Self { add_folder_string: Vec::new(), folders: Vec::new() }
}
}
impl App for MyApp {
fn update(&mut self, ctx: &Context, frame: &mut Frame) {
SidePanel::left("LeftPanel").show(ctx, |ui| {
ctx.set_visuals(Visuals { panel_fill: Color32::from_rgb(111, 255, 203), ..Visuals::default() });
ui.visuals_mut().extreme_bg_color = Color32::from_rgb(255, 255, 255);
if self.folders.len() > 0 {
for i in 0..self.folders.len() {
ui.group(|ui| {
ui.label(self.folders[i].clone());
if ui.button("Remove").clicked() { self.folders.remove(i); }
});
}
}
if ui.button("➕").clicked() {
self.folders.push(String::from("New Folder"));
}
});
}
}
I can remove the last folder I created but trying to remove the ones before that are causing panic
I tried to create a new Vec in MyApp struct and store the bools in it and remove the folders in another loop like this:
use eframe::{App, egui, Frame, NativeOptions, run_native};
use eframe::egui::{CentralPanel, Color32, Context, SidePanel, Visuals};
use crate::egui::RichText;
struct MyApp { add_folder_string: Vec<String>, folders: Vec<String>, remove_folder: Vec<bool> }
impl MyApp {
fn new(cc: &eframe::CreationContext<'_>) -> Self {
Self { add_folder_string: Vec::new(), folders: Vec::new(), remove_folder: Vec::new() }
}
}
impl App for MyApp {
fn update(&mut self, ctx: &Context, frame: &mut Frame) {
SidePanel::left("LeftPanel").show(ctx, |ui| {
ctx.set_visuals(Visuals { panel_fill: Color32::from_rgb(111, 255, 203), ..Visuals::default() });
ui.visuals_mut().extreme_bg_color = Color32::from_rgb(255, 255, 255);
self.remove_folder.resize(self.folders.len(), false);
if self.folders.len() > 0 {
for i in 0..self.folders.len() {
ui.group(|ui| {
ui.label(self.folders[i].clone());
if ui.button("Remove").clicked() { self.remove_folder[i] = true }
});
}
if self.remove_folder.contains(&true) {
for i in 0..self.remove_folder.len() {
if self.remove_folder[i] {
self.folders.remove(i);
self.remove_folder.remove(i);
}
}
}
}
if ui.button("➕").clicked() {
self.folders.push(String::from("New Folder"));
}
});
}
}
But this does the same thing I guess. I don't know why button().clicked "isn't working" in for loop
You could just store the indices of what to remove and then remove them rather than having 2 parallel Vec
s with still all the troubles of iterating while removing:
fn update(&mut self, ctx: &Context, frame: &mut Frame) {
SidePanel::left("LeftPanel").show(ctx, |ui| {
ctx.set_visuals(Visuals { panel_fill: Color32::from_rgb(111, 255, 203), ..Visuals::default() });
ui.visuals_mut().extreme_bg_color = Color32::from_rgb(255, 255, 255);
let mut remove = Vec::new();
for (i, folder) in self.folders.iter().enumerate() {
ui.group(|ui| {
ui.label(folder.clone());
if ui.button("Remove").clicked() {
remove.push(i)
}
});
}
// need to remove in reverse to not mess up later indices
for i in remove.into_iter().rev() {
self.folders.remove(i);
}
if ui.button("➕").clicked() {
self.folders.push(String::from("New Folder"));
}
});
}