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

基于Python/Kivy的MP3播放器:实现FileListView选歌播放功能

解决Kivy FileListView与SoundLoader结合实现MP3播放的问题

看起来你在搭建Kivy MP3播放器时遇到了回调逻辑和SoundLoader使用的问题,我帮你梳理下代码里的关键错误,并给出修正后的实现:

原代码的核心问题

  • 回调函数参数错误:FileChooser的on_selection回调会传递两个参数(组件实例和选中的文件列表),但你的load_sound只接收了一个参数;按钮的on_press回调也错误地定义了多余参数。
  • 未保存当前音频实例:没有把加载的Sound对象存在类属性里,导致播放/停止按钮无法访问到要操作的音频。
  • 文件路径处理错误:SoundLoader.load需要传入完整的MP3文件路径,而不是目录;获取选中文件的方式也不正确。
  • 音频控制逻辑混乱:加载、播放、停止的逻辑没有区分开,比如加载时直接播放,播放按钮又重复加载,停止按钮的unload用法错误。

修正后的完整代码

import os
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.filechooser import FileChooserListView
from kivy.core.audio import SoundLoader

red = [1, 0, 0, 1]
green = [0, 1, 0, 1]
blue = [0, 0, 1, 1]
purple = [1, 0, 1, 1]

class myLayout(BoxLayout):
    color = [red, green, blue, purple]
    path = '/home/edward/Music'

    def __init__(self, **kwargs):
        super(myLayout, self).__init__(**kwargs)
        self.current_sound = None  # 保存当前加载的音频实例
        layout = BoxLayout(pos=self.pos, size=self.size, spacing=10)
        self.add_widget(layout)

        # 文件选择列表
        flc = FileChooserListView(path=self.path, filters=['*.mp3'])
        flc.bind(on_selection=self.load_sound)
        layout.add_widget(flc)

        # 播放按钮
        play = Button(text="PLAY", valign='center', halign='center', 
                      background_color=blue, size_hint=(0.3, 0.5))
        play.bind(on_press=self.play_pressed)
        layout.add_widget(play)

        # 停止按钮
        stop = Button(text="STOP", valign='center', halign='center', 
                      size_hint=(0.3, 0.6), background_color=red)
        stop.bind(on_press=self.stop_pressed)
        layout.add_widget(stop)

        # 标题标签
        display = Label(text="kiwiAudioPlayer", halign='right')
        layout.add_widget(display)

    def load_sound(self, instance, selection):
        # 确保选中了文件
        if not selection:
            return
        
        # 先停止之前的音频(如果存在)
        if self.current_sound:
            self.current_sound.stop()
            self.current_sound.unload()
        
        # 获取选中的完整文件路径
        sound_path = selection[0]
        # 加载音频
        self.current_sound = SoundLoader.load(sound_path)
        if not self.current_sound:
            print(f"无法加载音频文件: {sound_path}")
        else:
            print(f"已加载音频: {os.path.basename(sound_path)}")

    def play_pressed(self, instance):
        # 检查是否有加载的音频
        if self.current_sound:
            # 如果音频正在播放,先停止再重新播放;否则直接播放
            if self.current_sound.status == 'play':
                self.current_sound.stop()
            self.current_sound.play()
        else:
            print("请先选中一个MP3文件")

    def stop_pressed(self, instance):
        if self.current_sound and self.current_sound.status == 'play':
            self.current_sound.stop()

class musicApp(App):
    def build(self):
        return myLayout()

if __name__ == "__main__":
    app = musicApp()
    app.run()

关键修正点说明

  1. 添加类属性self.current_sound:用来存储当前加载的音频对象,让播放/停止按钮能统一操作同一个实例。
  2. 修正回调函数参数:
    • load_sound改为接收instance(FileChooser实例)和selection(选中的文件列表)两个参数。
    • 播放/停止按钮的回调只接收按钮实例instance。
  3. 正确处理文件路径:通过selection[0]获取选中文件的完整路径,传给SoundLoader.load。
  4. 完善音频控制逻辑:
    • 加载新音频时,先停止并卸载之前的音频,避免资源占用。
    • 播放按钮先检查是否有加载的音频,再根据当前状态决定播放/重启。
    • 停止按钮只在音频播放时执行停止操作。

这样修改后,你点击FileListView里的MP3文件会自动加载,然后点击PLAY按钮就能播放,STOP按钮可以暂停播放,完全符合你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 18:37:57