簡體   English   中英

全局應用 state 帶FLTK庫

[英]Global application state with FLTK library

我正在使用 fltk 庫編寫應用程序。 該應用程序的架構涉及一個全局 state,它存儲現在顯示哪個頁面(查看器)並存儲查看器數據。 有一些按鈕可以發送消息來更新和更改全局 state,指示現在顯示哪個查看器。

#[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. 我的應用程序架構有效還是有更好的架構? 該應用程序有多個頁面(一頁一個查看器),每個查看器都有自己的全局 state 和存儲在其中並處理這些數據的數據。

  2. 在全局 state 中存儲觀眾數據的最佳方式是什么?

此代碼將您的 GlobalState 包裝在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();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM