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

Я хочу изменить метку кнопки при нажатии кнопки. Но я получил это сообщение об ошибке.

error[E0505]: cannot move out of `but` because it is borrowed
  --> src/main.rs:24:22
   |
24 |     but.set_callback(move || but.set_label("PRESSED"));
   |     --- ------------ ^^^^^^^ --- move occurs due to use in closure
   |     |   |            |
   |     |   |            move out of `but` occurs here
   |     |   borrow later used by call
   |     borrow of `but` occurs here

error: aborting due to previous error

Сам код

  1 use fltk::*;
  2 
  3 fn main() {
  4 
  5     let app = app::App::default().with_scheme(app::Scheme::Gleam);
  6     let mut win = window::Window::default()
  7         .with_pos(0, 0)
  8         .with_size(300, 300)
  9         .with_label("FLTK_Window");
 10     let mut but = button::Button::default()
 11         .with_pos(0, 0)
 12         .with_size(100, 50)
 13         .center_of(&win)
 14         .with_label("BUTTON");
 15     win.end();
 16     win.show();
 17     
 18     win.set_color(Color::Black);
 19     but.set_color(Color::from_rgb(0, 100, 0));
 20     but.set_label_color(Color::White);
 21     but.set_label_type(LabelType::Normal);
 22     but.set_callback(move || but.set_label("PRESSED"));
 23     app.run().unwrap();
 24 }

Как я могу справиться с такой проблемой?


person ratpoison    schedule 31.03.2021    source источник


Ответы (2)


Самое простое решение — clone but перед установкой обратного вызова, а затем переместить его в замыкание следующим образом:

use fltk::*;

fn main() {
    let app = app::App::default().with_scheme(app::Scheme::Gleam);
    let mut win = window::Window::default()
        .with_pos(0, 0)
        .with_size(300, 300)
        .with_label("FLTK_Window");
    let mut but = button::Button::default()
        .with_pos(0, 0)
        .with_size(100, 50)
        .center_of(&win)
        .with_label("BUTTON");
    win.end();
    win.show();

    win.set_color(Color::Black);
    but.set_color(Color::from_rgb(0, 100, 0));
    but.set_label_color(Color::White);
    but.set_label_type(LabelType::Normal);
    but.clone().set_callback(move || but.set_label("PRESSED"));
    app.run().unwrap();
}
person frankenapps    schedule 31.03.2021
comment
Спасибо, молодец, все работает! - person ratpoison; 31.03.2021

В дополнение к ответу frankenapps, у fltk есть перегруженный метод set_callback (set_callback2), который дает вам доступ к изменяемой ссылке виджета.

but.set_callback2(|b| b.set_label("PRESSED"));

Вы также можете использовать move для захвата внешних переменных, если вам это нужно.

Обновление: начиная с версии 1.0 fltk-rs, set_callback по умолчанию захватывает &mut self.

but.set_callback(|b| b.set_label("PRESSED"));
person xev    schedule 31.03.2021
comment
Спасибо. Он отлично работает! - person ratpoison; 31.03.2021