You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

fltk-rs中如何让闭包内的files变量在外部可访问?

问题原因

你在按钮回调里犯了一个关键错误:选择文件后,你没有修改共享的RefCell内部的Vec,而是重新创建了一个新的Rc<RefCell<Vec<PathBuf>>>并赋值给闭包内的files变量。这导致闭包内的files指向新实例,而MyApp结构体里的files仍指向最初的空Vec实例,两者不再共享数据。

修正方案

修改回调内的代码,通过borrow_mut()获取RefCell的可变引用,直接修改内部的Vec内容,而非替换整个Rc实例:

btn_files_select.set_callback({
    let files = files.clone(); // 克隆共享的Rc
    move |_| {
        let mut dialog = dialog::NativeFileChooser::new(dialog::NativeFileChooserType::BrowseMultiFile);
        if dialog.show() == dialog::NativeFileChooserResult::Ok { // 检查用户是否确认选择
            let selected_files = dialog.filenames();
            *files.borrow_mut() = selected_files; // 修改共享的RefCell内部Vec
        }
    }
});
完整修正后的代码
use fltk::{prelude::*, *};
use fltk_theme::{ColorTheme, WidgetTheme, ThemeType, color_themes};
use std::path::PathBuf;
use std::cell::RefCell;
use std::rc::Rc;

#[derive(Copy, Clone)]
pub enum Message {
    Send,
    Test,
}

#[derive(Clone)]
pub struct MyApp {
    app: app::App,
    main_window: window::Window,
    receiver: app::Receiver<Message>,
    input_host: input::Input,
    input_username: input::Input,
    input_password: input::SecretInput,
    files: Rc<RefCell<Vec<PathBuf>>>,
}

impl MyApp {
    pub fn new() -> Self {
        let app = app::App::default().with_scheme(app::Scheme::Base);
        let (s, receiver) = app::channel();
        let theme = ColorTheme::new(color_themes::BLACK_THEME);
        let widget_theme = WidgetTheme::new(ThemeType::AquaClassic);
        theme.apply();
        widget_theme.apply();
        let mut main_window = window::Window::default().with_size(800, 500).with_label("SSH conectivity").center_screen();
        main_window.make_resizable(true);
        let flex = group::Flex::default().with_size(300, 200).with_type(group::FlexType::Column).with_pos(100, 100);
        let _label_host = frame::Frame::default().with_size(40, 0).with_label("Hostname");
        let input_host = input::Input::default();
        let _label_username = frame::Frame::default().with_size(40, 0).with_label("User");
        let input_username = input::Input::default();
        let _label_password = frame::Frame::default().with_size(40, 0).with_label("Password");
        let input_password = input::SecretInput::default();
        let mut btn_files_select = button::Button::default().with_size(100, 30).with_label("Select files");
        flex.end();
        let mut button_send = button::Button::default().with_size(50, 40).with_pos(150, 350).with_label("Send");
        button_send.emit(s, Message::Send);
        let mut button_test = button::Button::default().with_size(50, 40).with_pos(250, 350).with_label("Test");
        button_test.emit(s, Message::Test);
        main_window.end();
        main_window.show();
        
        let files = Rc::new(RefCell::new(Vec::new())); // 简化初始化写法
        btn_files_select.set_callback({
            let files = files.clone();
            move |_| {
                let mut dialog = dialog::NativeFileChooser::new(dialog::NativeFileChooserType::BrowseMultiFile);
                if dialog.show() == dialog::NativeFileChooserResult::Ok {
                    *files.borrow_mut() = dialog.filenames();
                }
            }
        });
        
        Self { app, main_window, receiver, input_host, input_username, input_password, files }
    }
    pub fn run(mut self) {
        while self.app.wait() {
            if let Some(msg) = self.receiver.recv() {
                match msg {
                    Message::Send => {
                        println!("{:?}", self.files.borrow()); // 借用RefCell查看内容
                    },
                    Message::Test => {
                        println!("Test");
                    },
                }
            }
        }
    }
}
关键说明
  1. 用Rc::new(RefCell::new(Vec::new()))简化初始化,逻辑和原写法一致但更清晰。
  2. 回调内通过files.borrow_mut()获取可变引用,直接替换内部Vec,所有共享该Rc的地方都会同步看到更新后的内容。
  3. 增加对话框结果检查,避免用户取消选择时覆盖已有文件列表。

内容的提问来源于stack exchange,提问作者darkphoenix

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 18:15:30