0

我是 rust 新手,并且对 GTK 中的对象/变量的范围有疑问。我有以下代码,它有效,但我需要在 GTK 窗口中将标签设置为变量的文本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

4

1 回答 1

2

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

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

但这正是存在这个 other 的原因timeout_add_local(),它的工作原理和另一个一样,只是它不需要Send,并且必须从 GUI 线程调用它,否则它会恐慌。

于 2022-02-04T12:24:57.357 回答