'Toggling a bool from within a loop and Fn losure with rust and gtk

I'm trying to make a tic tac toe game with rust and gtk, and in order to swap turns I'm toggling bool when a game button is clicked. Because of the rust/gtk integration, the onclick events run within an Fn closure, so I can't directly edit a mutable reference to the bool.

Based on this post, I moved from a basic bool to a bool within a cell as that has interior mutability, allowing it to be varied from within the closure.

However, the variable gets moved into the closure, and in the next iteration of the loop/usage of xturn I get

--> src/main.rs:45:44
   |
39 |     let xturn = Cell::new(true);
   |         ----- move occurs because `xturn` has type `std::cell::Cell<bool>`, which does not implement the `Copy` trait
...
45 |             current_button.connect_clicked(move |current_button|{
   |                                            ^^^^^^^^^^^^^^^^^^^^^ value moved into closure here, in previous iteration of loop
46 |                 if current_button.label().unwrap() == ""{
47 |                     if xturn.get() {
   |                        ----- use occurs due to use in closure 

Code below

let game_grid: [[Button; 3];3] = [[new_game_button(), new_game_button(), new_game_button()],[new_game_button(), new_game_button(), new_game_button()],[new_game_button(), new_game_button(), new_game_button()]];
let xturn = Cell::new(true);

for i in 0..3{
    for o in 0..3{
        let current_button = &game_grid[i][o];
        grid.attach(current_button, i.try_into().unwrap(), o.try_into().unwrap(), 1, 1);
        current_button.connect_clicked(move |current_button|{
            if current_button.label().unwrap() == ""{
                if xturn.get() {
                    current_button.set_label("X");
                } else{
                    current_button.set_label("O");
                }; 
                xturn.set(!xturn.get());

            } else{
                println!("This spot is taken! Go Again.");
            }
            
        });

    }
}

Creating a reference to each use of xturn by adding & results in the same initial error message

Getting rid of the move at the start of the closure results in this error

error[E0373]: closure may outlive the current function, but it borrows `xturn`, which is owned by the current function

Complete code

use std::cell::Cell;
use gtk4 as gtk;
use gtk::{prelude::*, Label};
use gtk::{Align, Application, ApplicationWindow, Button, Grid};

fn main() {
    let app = Application::builder()
        .application_id("org.beribus.tictactoe")
        .build();

    app.connect_activate(build_ui);

    println!("Hello, world!");
    app.run();
}

fn build_ui(app: &gtk::Application){
    let window = ApplicationWindow::builder()
        .application(app)
        .default_width(360)
        .default_height(360)
        .title("GTK Tac Toe")
        .build();   

    let grid = Grid::builder()
        .margin_top(10)
        .margin_bottom(10)
        .margin_start(10)
        .margin_end(10)
        .halign(gtk::Align::Center)
        .valign(gtk::Align::Center)
        .row_spacing(6)
        .column_spacing(6)
        .build();

    window.set_child(Some(&grid));

    let game_grid: [[Button; 3];3] = [[new_game_button(), new_game_button(), new_game_button()],[new_game_button(), new_game_button(), new_game_button()],[new_game_button(), new_game_button(), new_game_button()]];
    let xturn = Cell::new(true);
    for i in 0..3{
        for o in 0..3{
            let current_button = &game_grid[i][o];
            grid.attach(current_button, i.try_into().unwrap(), o.try_into().unwrap(), 1, 1);
            current_button.connect_clicked(move |current_button|{
                if current_button.label().unwrap() == ""{
                    if xturn.get() {
                        current_button.set_label("X");
                    } else{
                        current_button.set_label("O");
                    }; 
                    &xturn.set(!&xturn.get());

                } else{
                    println!("This spot is taken! Go Again.");
                }
                
            });

        }
    }
    let text = Label::builder()
        .label("woro")
        .build();

    if xturn.get(){
        text.set_label("yoyooyo it's X's turn");
    } else{
        text.set_label("yoyooyo it's O's turn");
    }
    grid.attach(&text, 0,4,3,1);

    let reset_button = Button::builder()
        .halign(Align::Center)
        .valign(Align::Center)
        .label("Reset Game")
        .build();
    reset_button.connect_clicked(move |_|{
        for i in 0..3{
            for o in 0..3{
                let current_button = &game_grid[i][o];
                current_button.set_label("");
            }
        }
    });
    grid.attach(&reset_button, 0,3,3,1);

    window.show();
}

fn new_game_button() -> Button{
    let button = Button::builder()
        .halign(Align::Center)
        .valign(Align::Center)
        .label("")
        .width_request(90)
        .height_request(90)
        .build();
    button
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source