调用cursive.run()后,如何在按钮回调中创建并显示新Dialog?
解决Cursive中点击按钮后无法显示等待Dialog的问题
你的问题核心在于主线程被耗时操作阻塞,导致Cursive的UI事件循环无法刷新界面。原代码中thread::sleep直接在主线程执行,抢占了UI渲染的时机,新添加的Dialog根本没机会被绘制出来。
修改后的代码:
use std::thread; use std::time::Duration; use cursive::align::HAlign; use cursive::views::{Dialog, DummyView, LinearLayout, TextView}; use cursive::Cursive; use cursive::view::Resizable; fn main() { env_logger::init(); let mut siv = cursive::default(); siv.add_global_callback('q', Cursive::quit); siv.add_layer( Dialog::around( LinearLayout::vertical() .child(DummyView.fixed_height(1)) .child(TextView::new("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")) .child(DummyView.fixed_height(1)) ) .title("Parent Dialogue") .button("Save and Restart", save) .button("Cancel", |s| s.quit()) .h_align(HAlign::Center) ); siv.run(); } fn save(siv: &mut Cursive) { // 添加等待Dialog siv.add_layer( Dialog::around( LinearLayout::vertical() .child(DummyView.fixed_height(1)) .child(TextView::new("Please Wait...")) .child(DummyView.fixed_height(1)) ) .title("Restarting Service") .h_align(HAlign::Center) ); // 强制刷新UI,让Dialog立即显示 siv.refresh(); // 获取回调Sink,用于后台线程通知主线程退出 let cb_sink = siv.cb_sink().clone(); // 将耗时操作移到后台线程,避免阻塞主线程 thread::spawn(move || { // 模拟耗时的业务操作 thread::sleep(Duration::from_secs(10)); // 操作完成后发送退出命令 let _ = cb_sink.send(Box::new(|s| s.quit())); }); }
关键修改点:
- 强制UI刷新:添加Dialog后调用
siv.refresh(),直接通知Cursive立即更新界面,确保等待Dialog能及时显示。 - 后台执行耗时操作:用
thread::spawn把耗时逻辑移到后台线程,主线程回到UI事件循环,保证界面能完成渲染。 - 跨线程回调:通过
cb_sink()获取Cursive的回调接收器,后台线程完成工作后发送quit命令,让主线程退出程序,避免程序挂起。
内容的提问来源于stack exchange,提问作者fadedbee
相关产品推荐
相关产品推荐

