I'm trying to write a Gtk application. I have one function called build_ui to build the start-screen. Now I want to call a second function when a button gets clicked, however that called function has the app variable as parameter.
error[E0312]: lifetime of reference outlives lifetime of borrowed content...
--> src/main.rs:84:34
|
84 | user_interface::build_ui(app);
| ^^^
|
I had to make the parameter in build_ui static, because the compiler told me so.
The purpose of the second_function is to remove all the labels, buttons, objects,... in the window to replace them with other ones.
This means that every reference moved into the closure must live as long as the entire executable. You can hack around this with Rc to avoid using static borrows... But it really isn't pretty. Here's what I came up with (anyone feel free to speak up if there is a better way!)
Spoiler alert! :D
use gio::prelude::*;
use gtk::prelude::*;
use std::env::args;
use std::rc::Rc;
pub fn build_ui<T>(app: Rc<T>)
where
T: glib::IsA<gtk::Application>,
{
let win = gtk::ApplicationWindow::new(app.as_ref());
let btn_add = gtk::Button::new_with_label("Click me!");
//Event bindings
btn_add.connect_clicked(move |_button| {
println!("Add button clicked");
let app_clone = Rc::clone(&app);
second_function(app_clone);
});
win.add(&btn_add);
}
pub fn second_function<T>(_app: Rc<T>)
where
T: glib::IsA<gtk::Application>,
{
//Doing things here using the app-parameter...
}
fn main() {
let app = gtk::Application::new(Some("com.cat.manager"), Default::default())
.expect("Gtk initialization failed...");
let app = Rc::new(app);
let app_clone = Rc::clone(&app);
app.connect_activate(move |_app| {
build_ui(Rc::clone(&app_clone));
});
app.run(&args().collect::<Vec<_>>());
}
The double-Rc-clone in the connect_activate closure is intentional. It's necessary because of the Fn trait bound.
This solution makes me kind of ill. I hope there is a better way...