0

I'm trying to learn Rust and decided to play around with the FLTK crate. However, I'm having some issues trying to access button inside its own callback, and I'm not sure how to get around it.

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();
}

which results in the following error:

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

From what I understand, I cannot access button inside the callback, because I'm already using it as a mutable when calling the set_callback method on it. I don't know how I'm supposed to work around this issue.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Myrkvi
  • 133
  • 1
  • 5
  • 2
    It looks like your question might be answered by the answers of [Problems with mutability in a closure](https://stackoverflow.com/q/41990175/155423); [Can't borrow mutably within two different closures in the same scope](https://stackoverflow.com/q/49703990/155423). If not, please **[edit]** your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Apr 07 '20 at 14:35
  • @Shepmaster Thank you! It seems to work by putting the Button in a RefCell. – Myrkvi Apr 07 '20 at 14:45

1 Answers1

1

@Shepmaster linked Problems with mutability in a closure, which provided a solution for it.

button was changed into

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

and the callback was changed to:

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

The program now compiles and runs as expected.

Myrkvi
  • 133
  • 1
  • 5