I want to create a selectable and editable title for a folder in eframe/egui with the function egui::TextEdti::singleline(). But it needs mutable reference to string (&mut String). If I declare a variable in the function like this: let response = ui.add(egui::TextEdit::singleline(&mut "Add Folder".to_string())); I can edit the text but when I do it changes in this frame but in the next frame it becomes "Add Folder" again. I can't find a place to declare a &mut String variable. My code:
use eframe::{App, egui, Frame, NativeOptions, run_native};
use eframe::egui::{CentralPanel, Color32, Context, SidePanel, Visuals};
use crate::egui::RichText;
#[derive(Default)]
struct MyApp { add_folder_button_x: f32, add_folder_button_y: f32 }
impl MyApp {
fn new(cc: &eframe::CreationContext<'_>) -> Self {
Self { add_folder_button_x: 100., add_folder_button_y: 50. }
}
}
impl App for MyApp {
fn update(&mut self, ctx: &Context, frame: &mut Frame) {
SidePanel::left("LeftPanel").show(ctx, |ui| unsafe {
ctx.set_visuals(Visuals { panel_fill: Color32::from_rgb(111, 255, 203), ..Visuals::default() });
// The problem is here -------------------------------------VV
let response = ui.add(egui::TextEdit::singleline());
if response.changed() {}
ui.put(egui::Rect::from_points(&[egui::Pos2::new(self.add_folder_button_x, self.add_folder_button_y)]), egui::Button::new("➕").fill(Color32::RED).wrap(false));
});
CentralPanel::default().show(ctx, |ui| {
ctx.set_visuals(Visuals { panel_fill: Color32::from_rgb(111, 200, 203), ..Visuals::default() });
});
SidePanel::left("SecondLeft").show(ctx, |ui| {
ctx.set_visuals(Visuals { panel_fill: Color32::from_rgb(100, 200, 180), ..Visuals::default() });
if ui.button("Clicker").clicked() {}
if ui.add(egui::Button::new("➕").fill(Color32::RED)).clicked() {}
if ui.button(RichText::new("delete").color(Color32::RED)).clicked() {}
});
}
}
fn main() -> eframe::Result<()> {
let native_options = NativeOptions::default();
run_native("TASK", native_options, Box::new(|cc| Box::new(MyApp::new(cc))))
}
fn text_edit() -> String {
let mut single_line = "Add Folder".to_string();
single_line
}
I tried to create a function that returns (&'static mut String) but it had an error:
fn text_edit() -> &'static mut String {
let mut single_line = "Add Folder".to_string();
&mut single_line
// ^^^^^^^^^^^^^^^^ returns a reference to data owned by the current function error[E0515]
And i tried to declare a static variable that returns &mut String. But that also had an error:
static SINGLE_LINE: &mut String = &mut String::from("Add Folder");
// ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const From<&str>` is not implemented for `String`
And I looked in this post:text but it is doing it in loop in the "main" function, I am doing it in the implementation of App for MyApp so I cannot declare a variable outside of the fn update().
The issue you are facing is related to lifetimes and ownership in Rust. In your current implementation, you are trying to return a mutable reference to a local variable from the text_edit() function, which is not allowed as the local variable's lifetime is limited to the function scope.
To solve this problem, you can use a mutable String field within your MyApp struct to store the editable title. Here's how you can modify your code to achieve this:
By using the folder_title field in your MyApp struct, you can now have a mutable reference to the string and maintain its state between frames. When the user edits the text using the egui::TextEdit::singleline widget, the changes will persist across frames, and you can access the updated title through the folder_title field in your MyApp struct.
Remember that when working with mutable references, you need to be mindful of ownership and lifetimes to avoid common issues like borrowing and ownership conflicts.