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

【Rust GUI开发入门】编写一个本地音乐播放器(5. 制作音乐列表组件)

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

目的是要做一个这样的音乐列表组件:

songlist-view.png

包含:

  • 一个标题栏
  • 多个列表项

制作标题栏

需要在标题栏上显示排序图标,实现点击排序功能,因此额外需要定义一个枚举类型SortKey指示排序依据。这里的排序图标也手动绘制,不使用网络上的图标:

@rust-attr(derive(serde::Serialize, serde::Deserialize))
export enum SortKey {BySongName,BySinger,ByDuration,
}component SortIcon inherits Window {in-out property <bool> ascending:true;in-out property <bool> display:true;height: 15px;width: 15px;background: transparent;if !ascending && display: Path {MoveTo {x: 5;y: 1;}LineTo {x: 5;y: 9;}LineTo {x: 7;y: 7;}stroke: gray;stroke-width: 1px;}if ascending && display:Path {MoveTo {x: 5;y: 9;}LineTo {x: 5;y: 1;}LineTo {x: 3;y: 3;}stroke: gray;stroke-width: 1px;}
}component TitleBarItem inherits Window {in property <string> name:"name";in-out property <bool> display-sort-icon <=> arrow.display;in-out property <bool> ascending-sort <=> arrow.ascending;Rectangle {width: 100%;height: 100%;text := Text {text: name;color: dimgray;x: parent.width * 0.4;y: parent.height / 2 - self.height / 2;}arrow := SortIcon {ascending: true;width: 12px;height: 12px;x: text.x + text.width + 5px;y: parent.height / 2 - self.height / 2;}}
}export component TitleBar inherits Window {height: 30px;in-out property <SortKey> key;in-out property <bool> ascending;callback sort-items(SortKey, bool);VerticalLayout {HorizontalLayout {alignment: space-between;area1 := TouchArea {width: 33%;clicked => {sort-items(SortKey.BySongName, ascending);}TitleBarItem {width: 100%;height: 100%;name: @tr("Title");background: area1.has-hover ? Palette.control-background : transparent;display-sort-icon: key == SortKey.BySongName;ascending-sort: ascending;}}area2 := TouchArea {width: 33%;clicked => {sort-items(SortKey.BySinger, ascending);}TitleBarItem {name: @tr("Artist");height: 100%;width: 100%;background: area2.has-hover ? Palette.control-background : transparent;display-sort-icon: key == SortKey.BySinger;ascending-sort: ascending;}}area3 := TouchArea {width: 33%;clicked => {sort-items(SortKey.ByDuration, ascending);}TitleBarItem {name: @tr("Duration");height: 100%;width: 100%;background: area3.has-hover ? Palette.control-background : transparent;display-sort-icon: key == SortKey.ByDuration;ascending-sort: ascending;}}}Path {width: 100%;height: 5px;MoveTo {x: 0;y: 0;}LineTo {x: 100%;y: 0;}stroke: Palette.foreground;stroke-width: 0.3px;}}
}

制作列表项

每个列表项关联一首歌曲,显示其相关信息:

  • 歌名
  • 歌手
  • 时长

因此额外定义了一个SongInfo结构体。此外,双击该列表项会触发音乐播放,所以对外暴露一个double-clicked回调函数:

export struct SongInfo {id:int,song_name:string,singer:string,duration:string,song_path:string,
}export component SongItem inherits Window {height: 30px;in property <SongInfo> info:{ id:0, song_name:"xxx", singer:"xxx", duration:"xxx", song_path:"xxx" };callback double_clicked();background: area.has-hover ? Palette.control-background : transparent;VerticalLayout {area := TouchArea {double-clicked => {double_clicked();}HorizontalLayout {alignment: space-between;Rectangle {width: 33%;Text {width: 100%;x: parent.width * 0.4;text: info.song-name;overflow: elide;}}Rectangle {width: 33%;Text {width: 100%;x: parent.width * 0.4;text: info.singer;overflow: elide;}}Rectangle {width: 33%;Text {x: parent.width * 0.4;text: info.duration;}}}}Path {width: 100%;height: 1px;MoveTo {x: 0;y: 0;}LineTo {x: 100%;y: 0;}stroke: Palette.foreground;stroke-width: 0.15px;}}
}

把二者组合起来

使用Slint UI的内置ListView组件来渲染多个音乐项,然后竖直堆叠标题栏和这个ListView

export component SongListView inherits Window {in-out property <bool> ascending;in-out property <SortKey> sort-key;in-out property <SortKey> last-sort-key;in-out property <[SongInfo]> song-list;callback sort-songs(SortKey, bool);callback play-song(SongInfo, TriggerSource);VerticalLayout {width: 100%;height: 100%;TitleBar {ascending: root.ascending;key: root.sort-key;sort-items(key, ascending) => {if (root.last-sort-key == key) {root.sort-songs(key, !ascending);} else {root.sort-songs(key, true)}}}ListView {for item in root.song-list: SongItem {info: item;double_clicked => {root.play-song(item, TriggerSource.ClickItem);}}}}
}
http://www.dtcms.com/a/426957.html

相关文章:

  • 成都哪家公司做网站比较好h5网站建设机构
  • 少儿舞蹈小程序(20):手机号登录与多角色注册
  • 淘宝扭蛋机小程序的社交化运营策略
  • 跨会话泄露:AI时代下的安全挑战与防御策略
  • Nginx if指令安全使用指南
  • AI模型测评平台工程化实战十二讲(第五讲:大模型测评分享功能:安全、高效的结果展示与协作)
  • 2025文档管理软件推荐:效率、安全与协作全解析
  • 包头网站建设价格北京到广州高铁多长时间
  • 网站引导页分为三个板块设计风格天津站建站时间
  • HTML应用指南:利用POST请求获取全国中国工商农业银行网点位置信息
  • 【目标检测2025】
  • FLASK与JAVA的文件互传(单文件互传亲测)
  • Spring Boot + MyBatis plus + MySQL 实现位置直线距离实时计算
  • 大数据Spark(六十四):Spark算子介绍
  • 网页网站设计制作微信推广网站
  • WPF——效果和可视化对象
  • WPF 具有跨线程功能的UI元素
  • 河北众成建设有限公司网站做dw网站图片怎么下载地址
  • PHP基础-函数(第14天)
  • QwertyLearner+cpolar:如何远程提升英文输入效率?
  • 【题解】洛谷 P4081 [USACO17DEC] Standing Out from the Herd P [后缀数组 SA]
  • 论测试驱动开发DD
  • QCustomPlot 性能优化与问题排查
  • 建网站要多少钱用自己的服务器手机网站 图标
  • 需求分析:对原始需求进行加工提炼
  • SFT/DPO/PPO/GRPO训练全解析
  • 海康 智能相机二开 绘制底图+测试工具应用框
  • DIY主机无网络安装PVE全记录:手机热点+笔记本网络共享实战
  • 从“氛围编程“到“氛围研究“:OpenAI的GPT-5与未来自动化研究之路
  • 手动编译 OpenCV 4.1.0 源码,生成 ARM64 动态库 (.so),然后在 Petalinux 中打包使用。