如何在gtk-rs闭包内设置变量?

时间:2017-08-15 21:52:24

标签: rust gtk-rs

我正在建立一个降价应用,我希望保留两份文本副本,一份source文本,另一份TextBuffer包含所有正确的标签等。

我需要在闭包中设置此源字段的内容:

buffer.connect_begin_user_action(clone!(source => move |a| {
  let text = a.get_text(&a.get_start_iter(), &a.get_end_iter(), false).unwrap();
  source = text; // error: cannot assign to captured outer variable in an `Fn` closure

替代方案可能是在TextBuffer上设置一些属性,但我不知道这是否可行。

1 个答案:

答案 0 :(得分:1)

TextBufferExt::connect_begin_user_action()接受Fn - 闭包,即无法改变其捕获环境的闭包。当您需要更改无法更改的内容时,您可以使用内部可变性类型,例如RefCell

如果您要将source的类型调整为RefCell<String>并将封闭内的分配更改为*source.borrow_mut() = text;,代码将会编译,但还有另一个问题。您为克隆的source分配值。

clone!扩展为

{
    let source = source.clone();
    move |a| {
       let text = // ...
       // ...
    }
}

也就是说,闭包捕获并更改变量source的副本,而不是原始变量。 Rc是实现预期目标的方法之一

use std::cell::RefCell;
use std::rc::Rc;
// ...
let source = Rc::new(RefCell::new("Text".to_string()));
// ...
buffer.connect_begin_user_action(clone!(source => move |a| {
    let text = a.get_text(&a.get_start_iter(), &a.get_end_iter(), false).unwrap();
    *source.borrow_mut() = text;
    // ...
}));

另一种方法是删除clone!宏并通过引用捕获source(您需要在关闭之前删除move),但在这种情况下,它将无法用作{ {1}}期望一个生命周期为connect_begin_user_action()的闭包,这是一个没有捕获局部变量引用的闭包。