I'm new to rust and having trouble with the scope of objects/variables in GTK. I have the following code, which works, but I need to set a label in the GTK Window to the text of the variable watch_text
. Here is the code:
use adw::subclass::prelude::AdwApplicationWindowImpl;
use gtk::prelude::*;
use gtk::subclass::prelude::*;
use gtk::{gio, glib, CompositeTemplate};
use glib::{clone, DateTime, timeout_add};
use std::time::Duration;
use std::sync::{Arc, Mutex};
fn setup_signals(&self) {
let imp = imp::FurWindow::from_instance(self);
let running = Arc::new(Mutex::new(false));
imp.start_button.connect_clicked(clone!(@weak self as this, @strong running => move |_| {
if !*running.lock().unwrap() {
let mut secs: u32 = 0;
let mut mins: u32 = 0;
let mut hrs: u32 = 0;
this.inapp_notification("Starting Timer!");
*running.lock().unwrap() = true;
let stopwatch = DateTime::now_local();
let duration = Duration::new(1,0);
let timer_repeat = timeout_add(duration, clone!(@strong running as running_clone => move || {
if *running_clone.lock().unwrap() {
secs += 1;
if secs > 59 {
secs = 0;
mins += 1;
if mins > 59 {
mins = 0;
hrs += 1;
}
}
let watch_text: &str = &format!("{:02}:{:02}:{:02}", hrs, mins, secs).to_string();
println!("{}",watch_text);
// **Here the println works, everything prints correctly,
// but I need to add watch_text to the label "watch"
// this.set_watch_time(watch_text);
}
Continue(*running_clone.lock().unwrap())
}));
} else {
this.inapp_notification("Stopping Timer!");
*running.lock().unwrap() = false;
}
}));
}
The issue is that in the commented section, no matter how I try to access or clone imp.watch, I get an error NonNull<GObject> cannot be sent between threads safely
. How can I set the label text to watch_text
?
The issue is that timeout_add()
requires the passed callback to be Send
, which is nice, because with this function you can pass values from one working thread to the GUI thread, to be processed and update the interface accordingly.
But GUI objects are not Send
, because they live in the GUI thread and must be used only from the GUI thread, so they cannot be used for timeout_add()
.
But that is precisely why there is this other timeout_add_local()
, that works just like the other one, except that it does not require Send
, and that it must be called from the GUI thread, or else it will panic.