如何在 Rust 中设置 GTK 事件内结构的值?
我在尝试修改下面的 s
结构实例时遇到错误。
use gtk::prelude::*;
use gio::prelude::*;
use gtk::{Application, ApplicationWindow, Button};
struct SomeStruct {
val: bool,
}
fn main() {
let mut s = SomeStruct {
val: false,
};
application.connect_activate(|app| {
let window = ApplicationWindow::new(app);
window.set_title("test");
window.set_default_size(350,70);
let button = Button::with_label("Test");
button.connect_clicked(|_|{
s.val = true; // error here
});
window.add(&button);
window.show_all();
});
application.run(&[]);
}
错误消息:
error[E0597]: `s` does not live long enough
error[E0596]: cannot borrow `s` as mutable, as it is a captured variable in a `Fn` closure
最佳答案
您的代码有两个问题:
- 虽然
s
的生命周期比 GTK 应用程序的生命周期长,但 Rust 并不知道这一点,这就是它提示s
生命周期不够长的原因。 -
ButtonExt::connect_clicked()
接受Fn
,因此不允许在没有额外预防措施的情况下改变数据。
第一个问题可以通过在堆上分配 s
并通过 reference-counted pointer 访问它来解决。 ,这确保对象的生命周期至少与引用它的闭包一样长。
第二个问题最容易通过内部可变性解决,方法是将 SomeStruct
包装到 RefCell
中。 。 RefCell
保存一个值,并允许持有者通过对 RefCell
的共享引用来改变它。当请求对内部值的 mut
引用时,RefCell
将在运行时检查是否没有对该值的其他引用仍然存在。 (如果您的闭包要访问该值,然后在保存该值的同时调用另一个执行相同操作的闭包,则可能会发生这种情况。)
这两者结合起来会产生这样的代码(未经测试):
use std::rc::Rc;
use std::cell::RefCell;
fn main() {
let s = Rc::new(RefCell::new(SomeStruct { val: false }));
application.connect_activate(|app| {
let window = ApplicationWindow::new(app);
window.set_title("test");
window.set_default_size(350, 70);
let button = Button::with_label("Test");
// clone the handle to s and move it into the closure
let s2 = Rc::clone(&s);
button.connect_clicked(move |_| {
s2.borrow_mut().val = true;
});
window.add(&button);
window.show_all();
});
application.run(&[]);
}
关于rust - 如何在 Rust 中设置 GTK 事件内结构的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65049374/