Gtk-rs:在 glib::timeout_add 内设置标签

Gtk-rs: Set label within glib::timeout_add

我是 rust 的新手,在 GTK 中遇到 objects/variables 范围的问题。我有以下有效的代码,但我需要在 GTK Window 中将标签设置为变量 watch_text 的文本。这是代码:

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;
                }
            }));
        }

问题是在评论部分,无论我如何尝试访问或克隆 imp.watch,我都会收到错误 NonNull<GObject> cannot be sent between threads safely。如何将标签文本设置为 watch_text?

问题是 timeout_add() 要求传递的回调是 Send,这很好,因为使用此函数您可以将值从一个工作线程传递到 GUI 线程,以进行处理并相应地更新界面。

但 GUI 对象不是 Send,因为它们存在于 GUI 线程中,只能从 GUI 线程使用,所以它们不能用于 timeout_add()

但这正是另一个 timeout_add_local() 的原因,它的工作方式与另一个类似,只是它不需要 Send,并且必须从 GUI 线程调用, 不然会 panic.