Как получить доступ к кнопке FLTK внутри ее собственного обратного вызова?

Я пытаюсь изучить Rust и решил поиграться с крейтом FLTK. Тем не менее, у меня возникают проблемы с доступом к кнопке внутри ее собственного обратного вызова, и я не знаю, как это обойти.

use fltk::{app::*, button::*, frame::*, window::*};

fn main() {
    let app = App::default();
    let mut window = Window::new(100, 100, 400, 300, "Hello world!");

    let mut frame = Frame::new(0, 0, 400, 200, "");
    let mut button = LightButton::default()
        .with_pos(10, 10)
        .with_size(80, 40)
        .with_label("Clickity");

    button.set_callback(Box::new(|| {
        println!("Button is {}", button.is_on());
        frame.set_label(&format!("{}", button.is_on()))
    }));
    window.show();
    app.set_scheme(AppScheme::Gleam);
    app.run().unwrap();
}

что приводит к следующей ошибке:

error[E0502]: cannot borrow `button` as mutable because it is also borrowed as immutable
  --> src/main.rs:15:5
   |
15 |       button.set_callback(Box::new(|| {
   |       ^      ------------          -- immutable borrow occurs here
   |       |      |
   |  _____|      immutable borrow later used by call
   | |
16 | |         println!("Button is {}", button.is_on());
   | |                                  ------ first borrow occurs due to use of `button` in closure
17 | |         frame.set_label(&format!("{}", button.is_on()))
18 | |     }));
   | |_______^ mutable borrow occurs here

Насколько я понимаю, я не могу получить доступ к button внутри обратного вызова, потому что я уже использую его как изменяемый при вызове на нем метода set_callback. Я не знаю, как я должен обойти эту проблему.


person Myrkvi    schedule 07.04.2020    source источник
comment
Похоже, на ваш вопрос могут ответить ответы Проблемы с изменчивостью в замыкании; Невозможно заимствовать в двух разных замыканиях в одной области. Если нет, отредактируйте свой вопрос, чтобы объяснить различия. В противном случае мы можем пометить этот вопрос как уже отвеченный.   -  person Shepmaster    schedule 07.04.2020
comment
@Шепмастер Спасибо! Кажется, это работает, помещая кнопку в RefCell.   -  person Myrkvi    schedule 07.04.2020


Ответы (1)


@Shepmaster связал проблемы с изменчивостью в замыкании, что дало для них решение .

button был изменен на

    let button = ::std::cell::RefCell::new(
        LightButton::default()
            .with_pos(10, 10)
            .with_size(80, 40)
            .with_label("Clickity"),
    );

и обратный вызов был изменен на:

    button.borrow_mut().set_callback(Box::new(|| {
        let button = button.borrow();
        println!("Button is {}", button.is_on());
        frame.set_label(&format!("{}", button.is_on()))
    }));

Теперь программа компилируется и работает, как и ожидалось.

person Myrkvi    schedule 07.04.2020