0

我正在使用 kivy recycleview 创建一个 mp3 播放器,该应用程序在播放列表屏幕中有很多按钮,每当您单击一个按钮时,该按钮的图标就会从“播放”变为“暂停”,反之亦然。

我想知道如何使它成为单击另一个按钮将所有其他按钮图标更改为“播放”的方式,只有选定的按钮应该带有“暂停”图标。

.py 文件:

from kivy.lang import Builder
from kivymd.app import MDApp
from kivy.core.window import Window
from kivy.properties import StringProperty, ObjectProperty
from kivymd.theming import ThemableBehavior
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.screen import MDScreen
from kivymd.uix.behaviors import RectangularRippleBehavior
from kivy.uix.behaviors import ButtonBehavior

from kivy.clock import Clock

Builder.load_file('playlist.kv')

KV = """
#:import FadeTransition kivy.uix.screenmanager.FadeTransition

ScreenManager:
    transition: FadeTransition()

    Playlist:
        name: "playlist screen"

"""

class Playlist(ThemableBehavior, MDScreen):
    rv = ObjectProperty()
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        Clock.schedule_once(self._finish_init)

    def music_list(self):
        return ['audio '+str(i) for i in range(1, 121)]

    def _finish_init(self, dt):
        self.set_list_musics()
        
    def set_list_musics(self):
        """Builds a list of audios for the screen Playlist."""
        print(self.ids)

        def add_music_item(num, sura, secText, icon):
            self.ids.rv.data.append(
                {
                    "viewclass": "MusicListItem",
                    "number": num,
                    "text": sura,
                    "secondary_text": secText,
                    "icon": icon,
                    "callback": lambda x:x})
    
        for i in range(len(self.music_list())):
            music = self.music_list()
            add_music_item(str(i+1), music[i], '00:00:00', 'play')
         
    
class MusicListItem(ThemableBehavior, RectangularRippleBehavior, ButtonBehavior, MDBoxLayout):
    text = StringProperty()
    secondary_text = StringProperty()
    number = StringProperty()
    icon = StringProperty()
    
    def on_release(self, *args):
        if self.icon == "play":
            self.icon = "pause"
        else:
            self.icon = "play"
    
    
class Mp3Player(MDApp):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
       
    def build(self):
        self.theme_cls.primary_palette = "Purple"
        self.theme_cls.theme_style = "Dark"
        return Builder.load_string(KV)


if '__main__' == __name__:
    Mp3Player().run()

.kv 文件:

#: import gch kivy.utils.get_color_from_hex
#: import StiffScrollEffect kivymd.effects.stiffscroll.StiffScrollEffect

<Playlist>
    md_bg_color: gch("#5D1049")
        
    MDGridLayout:
        cols: 1
        
        MDToolbar:
            left_action_items: [["menu", lambda x: x]]
            right_action_items: [["magnify", lambda x: x]]
            elevation: 10
            md_bg_color: 75/255, 6/255, 54/255, 1
            title: 'Playlist'
            pos_hint: {'top':1}
                    
        MDBoxLayout:
            orientation: 'vertical'
           
            RecycleView:
                id: rv
                effect_cls: 'ScrollEffect'
                viewclass: 'MusicListItem'

                RecycleBoxLayout:
                    padding: dp(10)
                    default_size: None, dp(60)
                    default_size_hint: 1, None
                    size_hint_y: None
                    height: self.minimum_height
                    orientation: 'vertical'

     
<MusicListItem>
    size_hint_y: None
    padding: dp(14)
    height: dp(60)

    canvas:
        Color:
            rgba:
                self.theme_cls.divider_color
        Line:
            points: (root.x+dp(10), root.y, root.x+self.width-dp(10)-0, root.y)

    MDBoxLayout:
        orientation: "horizontal"
        pos_hint: {"center_x": .5, "center_y": .5}

        MDBoxLayout:
            orientation: 'horizontal'
            MDBoxLayout:
                orientation: 'vertical'
                size_hint_x: .2
              
                MDLabel:
                    text: root.number
                    font_style: "H6"
                    adaptive_height: True
                
                MDLabel:
                    size_hint_y: .3
                 
            MDBoxLayout:
                orientation: 'vertical'
             
                MDLabel:
                    text: root.text
                    font_style: "Subtitle2"
                    adaptive_height: True
    
                MDLabel:
                    text: root.secondary_text
                    font_style: "Caption"
                    theme_text_color: "Hint"
                    adaptive_height: True

            MDIconButton:
                icon: root.icon          
    

谢谢

4

1 回答 1

2

因此,据我了解,您希望将一个图标设置为“暂停”,而将所有其他图标设置为“播放”。这样做的一种方法可能是,每次图标更改时都必须重新加载RecyclView 数据。

  1. 现在要提供带有图标引用的数据number(即“播放”或“暂停”),我发现该属性合适,所以我将其更改为NumericProperty. 因此number = NumericProperty()

  2. 这也需要对 kv 进行一些更改,

                MDLabel:
                    text: str(int(root.number))
                    font_style: "H6"
                    adaptive_height: True
  1. Playlist了解number参考,
    def set_list_musics(self, music_no = 0):
        """Builds a list of audios for the screen Playlist."""
        print(self.ids)
        self.ids.rv.data = [ ] # Since you are appending data and we need to reload everytime.
  1. 对数据进行必要的更改,
        for i in range(len(self.music_list())):
            new_icon = 'pause' if i+1 == music_no else 'play'
            music = self.music_list()
            add_music_item(str(i+1), music[i], '00:00:00', new_icon)
  1. 现在是最后一部分,通过按钮触发更改,
    def on_release(self, *args):
        if self.icon == "play":
            self.icon = "pause"
            pl = self.parent.parent.parent.parent.parent # Accessing the Playlist according to your design pattern.
            pl.set_list_musics(self.number)
        else:
            self.icon = "play"

请注意,我在“暂停”图标中进行了此更改(即在 中if self.icon == "play"),因此您也可以自由切换此图标。否则放置它无法使其成为可能。

也许这可以通过其他设计风格更系统地完成。我发现您的设计模式存在一些问题。这(例如在循环中重复调用函数等)可能会使它随着数据的增加而for变慢。

于 2022-01-16T11:02:33.897 回答