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.
我是 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.