rust 使用FLTK库的全局应用程序状态

w7t8yxp5  于 2023-01-30  发布在  其他
关注(0)|答案(1)|浏览(208)

我正在使用fltk库编写一个应用程序,该应用程序的架构包括一个全局状态,它存储现在要显示的页面(查看器)和查看器数据,还有一些按钮发送消息更新和更改全局状态,指示现在要显示的查看器。

#[derive(Clone, Copy)]
enum Message {
    Update
}

#[derive(Clone, Copy)]
struct GlobalState {
    viewer: Viewer,
}

impl GlobalState {
    fn set_viewer(&mut self, v: Viewer) {
        self.viewer = v;
    }
}

#[derive(Clone, Copy)]
enum Viewer {
    Page1,
    Page2
}

fn main() {
    let mut gs = GlobalState {viewer: Viewer::Page1};

    let app = app::App::default().with_scheme(app::Scheme::Gtk);
    let (s, r) = app::channel::<Message>();
    let mut wind = Window::default().with_size(800, 600);

    left_side(&mut gs);

    let mut col = Column::new(155,70,800 - 150,600 - 65,None);
    s.send(Message::Update);
    col.end();
    wind.end();
    wind.show();

    while app.wait() {
        if let Some(msg) = r.recv() {
            match msg {
                Message::Update => {
                    match gs.viewer {
                        Viewer::Page1 => {
                            col.clear();
                            let view = view_ohm();
                            col.add(&view);
                        },
                        Viewer::Page2 => {
                            col.clear();
                            let view = view_ohm();
                            col.add(&view);
                        },
                        _ => ()
                    }
                }
                _ => (),
            }
        }
    }
}

fn left_side(gs: &mut GlobalState) {
    let btn_width = 130;
    let btn_height = 30;

    let (s, r) = app::channel::<Message>();

    let mut grp = Group::default().with_size(65, 600);
    let mut col = Pack::default()
        .with_size(btn_width, 600)
        .center_of_parent()
        .with_type(PackType::Vertical);
    col.set_spacing(2);

    let mut btn = Button::new(0, 0, btn_width, btn_height, "Page 1");
    btn.emit(s, Message::Update);
    btn.set_callback(|_| {
        gs.set_viewer(Viewer::Page1)
    });

    let mut btn = Button::new(0, 0, btn_width, btn_height, "Page 2");
    btn.emit(s, Message::Update);
    btn.set_callback(|_| {
        gs.set_viewer(Viewer::Page2)
    });

    col.end();
    grp.end();
}

问题:
1.代码未编译,错误为:

error[E0521]: borrowed data escapes outside of function
      --> src/main.rs:89:5
       |
    74 |   fn left_side(gs: &mut GlobalState) {
       |                --  - let's call the lifetime of this reference `'1`
       |                |
       |                `gs` is a reference that is only valid in the function body
    ...
    89 | /     btn.set_callback(|_| {
    90 | |         gs.set_viewer(Viewer::Page1)
    91 | |     });
       | |      ^
       | |      |
       | |______`gs` escapes the function body here
       |        argument requires that `'1` must outlive `'static`
    
    error[E0524]: two closures require unique access to `*gs` at the same time
      --> src/main.rs:95:22
       |
    89 |       btn.set_callback(|_| {
       |       -                --- first closure is constructed here
       |  _____|
       | |
    90 | |         gs.set_viewer(Viewer::Page1)
       | |         -- first borrow occurs due to use of `*gs` in closure
    91 | |     });
       | |______- argument requires that `*gs` is borrowed for `'static`
    ...
    95 |       btn.set_callback(|_| {
       |                        ^^^ second closure is constructed here
    96 |           gs.set_viewer(Viewer::Page2)
       |           -- second borrow occurs due to use of `*gs` in closure

1.我的应用程序体系结构是否正常工作?应用程序有几个页面(一个页面一个查看器),每个查看器都有自己的全局状态和存储在其中的数据,并处理这些数据。
1.在全局状态中存储查看器数据的最佳方法是什么?

jchrr9hc

jchrr9hc1#

此代码将您的GlobalState Package 在Rc<RefCell<GlobalState>>中:

#[derive(Clone, Copy)]
enum Message {
    Update
}

#[derive(Clone, Copy)]
struct GlobalState {
    viewer: Viewer,
}

impl GlobalState {
    fn set_viewer(&mut self, v: Viewer) {
        self.viewer = v;
    }
}

#[derive(Clone, Copy)]
enum Viewer {
    Page1,
    Page2
}

fn main() {
    let mut gs = Rc::new(RefCell::new(GlobalState {viewer: Viewer::Page1}));

    let app = app::App::default().with_scheme(app::Scheme::Gtk);
    let (s, r) = app::channel::<Message>();
    let mut wind = Window::default().with_size(800, 600);

    left_side(gs.clone());

    let mut col = Column::new(155,70,800 - 150,600 - 65,None);
    col.end();
    wind.end();
    wind.show();

    while app.wait() {
        if let Some(msg) = r.recv() {
            match msg {
                Message::Update => {
                    let gs = gs.borrow();
                    match gs.viewer {
                        Viewer::Page1 => {
                            col.clear();
                            let view = view_ohm();
                            col.add(&view);
                        },
                        Viewer::Page2 => {
                            col.clear();
                            let view = view_ohm();
                            col.add(&view);
                        },
                        _ => ()
                    }
                }
                _ => (),
            }
        }
    }
}

fn left_side(gs: Rc<RefCell<GlobalState>>) {
    let btn_width = 130;
    let btn_height = 30;

    let s = app::Sender::get();

    let mut grp = Group::default().with_size(65, 600);
    let mut col = Pack::default()
        .with_size(btn_width, 600)
        .center_of_parent()
        .with_type(PackType::Vertical);
    col.set_spacing(2);

    let mut btn = Button::new(0, 0, btn_width, btn_height, "Page 1");

    btn.set_callback({
        let gs = gs.clone();
        move |_| {
        gs.borrow_mut().set_viewer(Viewer::Page1);
        s.send(Message::Update);
    }});

    let mut btn = Button::new(0, 0, btn_width, btn_height, "Page 2");

    btn.set_callback(move |_| {
        gs.borrow_mut().set_viewer(Viewer::Page2);
        s.send(Message::Update);
    });

    col.end();
    grp.end();
}

相关问题