Как установить переменную внутри 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 ответ
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
до закрытия), но в этом случае он не будет работать как connect_begin_user_action()
ожидает закрытия с 'static
время жизни, это замыкание без захваченных ссылок на локальные переменные.