1

I'm getting these error messages in my gkt-rs code:

error[E0507]: cannot move out of `image`, a captured variable in an `Fn` closure
error[E0382]: borrow of moved value: `window`

I've read this question and this question, but don't see how to apply it to my problem. I assume the answer involves RefCell, but can't get the invocation right.

This is my code:

use gtk::prelude::*;
use gtk::{Application, ApplicationWindow, Box, Button, FileChooserDialog, Image};
const APP_ID: &str = "org.gtk_rs.test";

fn main() {
    let app = Application::builder().application_id(APP_ID).build();
    app.connect_activate(build_ui);
    app.run();
}

fn build_ui(app: &Application) {
    let image = Image::builder().build();
    let button = Button::builder().label("Press me!").build();
    let mbox = Box::builder().build();
    mbox.append(&button);
    mbox.append(&image);
    let window = ApplicationWindow::builder()
        .application(app)
        .title("My GTK App")
        .child(&mbox)
        .build();
    button.connect_clicked(move |_| {
        let file_chooser = FileChooserDialog::new(
            Some("Open image"),
            Some(&window),
            gtk::FileChooserAction::Open,
            &[
                ("_Cancel", gtk::ResponseType::Cancel),
                ("_Open", gtk::ResponseType::Accept),
            ],      );
            file_chooser.connect_response(move |file_chooser, response| {
                if response == gtk::ResponseType::Accept {
                    let file = file_chooser.file().expect("Couldn't get file");
                    let filename = file.path().expect("Couldn't get file path");
                    image.set_from_file(Some(filename));
                }
                file_chooser.destroy();
            });
        file_chooser.show();
    });
    window.present();
}

I'd be grateful for any suggestions.

DobbyTheElf
  • 604
  • 6
  • 21
  • how about not using `move |_| {}`, just borrow stuff in the closure `|_| {}` – alexzander Dec 28 '22 at 11:50
  • from where did you get this example? did you make it yourself? are there some gtk examples? im pretty sure they are not erroneus – alexzander Dec 28 '22 at 11:51
  • "I'm getting these error messages in my gkt-rs code" rustc compilation errors usually give details. These are useful to diagnose issues, because they provide contexts and what rustc is unhappy with. Though in this case the first obvious thing is that you're `move`-ing` `window` into the button's callback, then you're trying to call `window.present()`. Can't have your take and eat it there. Same issue in reverse for `image`: you're trying to `move` it into the callback, but there's an extnat borrow from when you `append`-ed it to the mbox. – Masklinn Dec 28 '22 at 11:51
  • @alexzander I'd assume they resorted to a `move` closure because the callback is not scoped, so a regular borrow did not work either. – Masklinn Dec 28 '22 at 11:52
  • 1
    @DobbyTheElf check out these older posts: https://stackoverflow.com/a/31967816/8182118 https://stackoverflow.com/questions/45702112/how-to-set-a-variable-inside-a-gtk-rs-closure also [the gtk-rs examples folder](https://github.com/gtk-rs/gtk3-rs/tree/master/examples): complicated crates usually have one such, and they can be invaluable in finding the right patterns. For instance [text viewer](https://github.com/gtk-rs/gtk3-rs/blob/master/examples/text_viewer/main.rs) reveals [a clone macro](https://gtk-rs.org/gtk-rs-core/stable/latest/docs/glib/macro.clone.html) which seems exactly for this. – Masklinn Dec 28 '22 at 12:00
  • @alexzander: if I remove the `move` and add `.borrow()` to the window references, I get: `the trait IsA is not implemented for Ref<'_, ApplicationWindow>` – DobbyTheElf Dec 28 '22 at 13:42
  • @alexzander: I cut the example code down from the app I am building. – DobbyTheElf Dec 28 '22 at 13:46

1 Answers1

1

Thanks @Masklinn, the text_viewer example had the answer:

use glib_macros::clone;
use gtk::prelude::*;
use gtk::{Application, ApplicationWindow, Box, Button, FileChooserDialog, Image};
const APP_ID: &str = "org.gtk_rs.test";

fn main() {
    let app = Application::builder().application_id(APP_ID).build();
    app.connect_activate(build_ui);
    app.run();
}

fn build_ui(app: &Application) {
    let image = Image::builder().build();
    let button = Button::builder().label("Press me!").build();
    let mbox = Box::builder().build();
    mbox.append(&button);
    mbox.append(&image);
    let window = ApplicationWindow::builder()
        .application(app)
        .title("My GTK App")
        .child(&mbox)
        .build();
    button.connect_clicked(clone!(@weak window => move |_| {
        let file_chooser = FileChooserDialog::new(
            Some("Open image"),
            Some(&window),
            gtk::FileChooserAction::Open,
            &[
                ("_Cancel", gtk::ResponseType::Cancel),
                ("_Open", gtk::ResponseType::Accept),
            ],      );
            file_chooser.connect_response(clone!(@weak image => move |file_chooser, response| {
                if response == gtk::ResponseType::Accept {
                    let file = file_chooser.file().expect("Couldn't get file");
                    let filename = file.path().expect("Couldn't get file path");
                    image.set_from_file(Some(filename));
                }
                file_chooser.destroy();
            }));
        file_chooser.show();
    }));
    window.present();
}
DobbyTheElf
  • 604
  • 6
  • 21