当前位置: 首页 > news >正文

【Rust GUI开发入门】编写一个本地音乐播放器(3. UI与后台线程通信)

本系列教程对应的代码已开源在 Github zeedle

UI线程 →消息\xrightarrow{消息}消息 后台线程

使用枚举定义消息类型

enum PlayerCommand {Play(SongInfo, TriggerSource), // 从头播放某个音频文件Pause,                         // 暂停/继续播放ChangeProgress(f32),           // 拖拽进度条PlayNext,                      // 播放下一首PlayPrev,                      // 播放上一首SwitchMode(PlayMode),          // 切换播放模式RefreshSongList(PathBuf),      // 刷新歌曲列表SortSongList(SortKey, bool),   // 排序歌曲列表SetLang(String),               // 设置语言
}

通过管道发送数据

从UI主线程通过管道(channel)向后台线程发送信息,例如:

// UI 主线程
...
let (tx, rx) = std::sync::channel::<PlayerCommand>();
std::thread::spawn(move || {// 后台线程while let Ok(cmd) = rx.recv() {match cmd {PlayerCommand::Pause => {...},PlayerCommand::PlayNext => {...},PlayerCommand::PlayNext => {...},....}}
});...
tx.send(PlayerCommand::Pause);
...

后台线程 →消息\xrightarrow{消息}消息 UI线程

全局状态

Slint UI支持在.slint文件中声明全局变量,然后在Rust代码中访问/修改该变量的值,这样即可完成UI状态的更新:

// ui state
export global UIState {// 当前播放进度 (秒)in-out property <float> progress;// 总时长 (秒)in-out property <float> duration;// 当前播放进度文本in-out property <string> progress_info_str;// 播放/暂停状态in-out property <bool> paused;// 是否正在拖动进度条in-out property <bool> dragging;// 歌曲列表in-out property <[SongInfo]> song_list;// 当前播放歌曲的信息in-out property <SongInfo> current_song;// 播放模式in-out property <PlayMode> play_mode;// 是否已被用户触发播放in-out property <bool> user_listening;// 当前播放歌曲的歌词in-out property <[LyricItem]> lyrics;// 当前歌词视窗的滚动条位置(一般为负数)in property <length> lyric_viewport_y;// 当前一行歌词的高度in-out property <length> lyric_line_height: 40px;// 歌曲文件夹配置in-out property <string> song_dir;// 关于信息in property <string> about_info;// 专辑封面图像in property <image> album_image;// 播放历史in property <[SongInfo]> play_history;// 播放历史索引in property <int> history_index: 0;// 歌曲排序方式in-out property <SortKey> sort_key;in-out property <SortKey> last_sort_key;// 升序/降序in-out property <bool> sort_ascending: true;// 当前语言in-out property <string> lang;// 主题颜色in-out property <bool> light_ui;
}

从后台线程添加任务到UI主线程

与上文中使用管道发送指令不同,Slint UI提供了一种从后台线程发送指令到UI主线程的简便方式,即通过slint::invoke_from_event_loop(task_closure),将task添加到UI主线程的下一轮事件循环中执行,更新UI状态,例如:

// 后台线程
let ui_weak = ui.as_weak();
while let Ok(cmd) = rx.recv() {match cmd {PlayerCommand::Pause => {...slint::invoke_from_event_loop(move || {// 此闭包虽然在后台线程中定义,但是执行是发生在UI主线程里面的// 只有在UI主线程中才能获得UI窗口对象的强引用,否则会失败if let Some(ui) = ui_weak.upgrade(){let ui_state = ui.global::<UIState>();ui_state.set_paused(true);}})...},}
}

总结

在Slint UI中,一种典型的范式是:

  • UI线程通过管道向后台线程发送数据
  • .slint中定义的全局变量(export global {...})可以在Rust代码中直接使用
  • 后台线程通过slint::invoke_from_event_loop(task_closure)向UI主线程的事件循环中添加任务,典型做法是此任务修改上述全局变量(即UIState),来完成UI状态更新
http://www.dtcms.com/a/423132.html

相关文章:

  • P11013 「ALFR Round 4」C 粉碎 题解
  • 跨境商城网站建设公司做小程序要多少钱
  • scratch绘制帽子花 2025年6月中国电子学会图形化编程 少儿编程 scratch编程等级考试三级真题和答案解析
  • 特色专业建设展示网站北京seo培训
  • 网络原理-HTTP补充1
  • 做外贸相关的网站全面的vi设计公司
  • 如何构建高效 AI 智能体
  • 9.25训练赛+Codeforces1054 (Div. 3)
  • 老Java项目访问提示orcale 19c ORA-01017: 用户名/口令无效; 登录被拒绝
  • 目标检测:yolov7算法在RK3588上部署
  • Maya Python: 安装pymel
  • 全景网站开发待遇南宁logo设计公司
  • 北京工商局网站怎么做增资网易代理暴雪
  • 制造行业订单全生命周期管理数仓项目实战
  • 《深度学习入门:基于Python的理论与实现》第7章 卷积神经网络笔记
  • 网络游戏编程 - Socket 技术以及应用 - 上 -《了解游戏网络基础知识》
  • 珠海建网站的网络公司网站名称格式
  • 舆情观察类文章写作指南与新浪舆情通应用
  • C语言——深入理解函数声明定义和调用访问
  • 网站开发大约多少钱制作一个网站的步骤是什么
  • RabbitMQ (一)简单模式
  • 阿里巴巴 Java 开发手册 v1.2.0
  • Leetcode+Java+单调栈
  • Word和WPS文字如何从特定的页开始编号(页码)?
  • EDSR模型
  • thinkphp做中英文网站网站跟app区别
  • 6. 数据库设计基础知识
  • 【nginx平滑升级演示】
  • 桥梁缺陷检测数据集:腐蚀、剥落、渗透等5类,3k+图像,yolo标注
  • 上交提出单图生成3D场景方法SceneGen:单图输入,多资源输出,3D 合成性能飙升的“秘密武器”!