kivymd Card 在循环的帮助下滚动列表项?

kivymd Card scroll list items with the help of loop?

我正在开发一个移动应用程序,我想使用 for 循环创建多个 scoll 项,但是每当我使用 for loop 时,都会出现一些错误 It has already parent widget。我怎样才能列出 MDCard?

我的应用: Click here

我的代码:

from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.screenmanager import Screen, ScreenManager
from kivymd.uix.boxlayout import BoxLayout
from kivy.uix.image import AsyncImage
from kivymd.uix.card import MDCard
from kivymd.uix.label import MDLabel

Window.size = (450, 740)

kv = '''
ScreenManager:
    Main:

<main>:
    name: 'main'
    video_list: video_list
    BoxLayout:
        orientation: 'vertical'
        MDToolbar:
            title: 'Video downloader'

        ScrollView:
            Screen:
                id: video_list
     '''

class Main(Screen):
    pass

sm = ScreenManager()
sm.add_widget(Main(name='main'))

class Ytube(MDApp):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.theme_cls.colors = 'Red'
        self.theme_cls.primary_palette = "Red"
        self.root = Builder.load_string(kv)

        image = AsyncImage(
            source='https://static.hub.91mobiles.com/wp-content/uploads/2020/05/How-to-download-youtube-videos.jpg', size_hint=(1, .7), )
        screen_id = self.root.get_screen('main').ids.video_list

        for i in range(1):
            card = MDCard(orientation='vertical', pos_hint={
                            'center_x': .5, 'center_y': .7}, size_hint=(.9, .4))
            card.add_widget(image)
            card.add_widget(MDLabel(
                text='Phishing attacks are SCARY easy to do!! (let me show you!)', size_hint=(.6, .2), ))
            screen_id.add_widget(card)

    def build(self):
        return self.root

if __name__ == "__main__":
    Ytube().run()

有什么办法可以做到 look like this.

问题是您试图对每个 MDCard 使用相同的 image 小部件。任何小部件只能有一个 parent。您只能使用该 image 小部件一次。您可以通过在循环内移动 image 小部件的创建来解决此问题。

此外,BoxLayoutScrollView 的 child 的更好选择,因为它有一个 minimum_height 属性,您可以使用.这是您的代码的修改版本,它应用了这两个建议:

from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.uix.image import AsyncImage
from kivymd.uix.card import MDCard
from kivymd.uix.label import MDLabel

Window.size = (450, 740)

kv = '''
ScreenManager:
    Main:

<main>:
    name: 'main'
    video_list: video_list
    BoxLayout:
        orientation: 'vertical'
        MDToolbar:
            title: 'Video downloader'

        ScrollView:
            do_scroll_x: False
            BoxLayout:
                id: video_list
                orientation: 'vertical'
                size_hint_y: None
                height: self.minimum_height
     '''

class Main(Screen):
    pass

sm = ScreenManager()
sm.add_widget(Main(name='main'))

class Ytube(MDApp):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.theme_cls.colors = 'Red'
        self.theme_cls.primary_palette = "Red"
        self.root = Builder.load_string(kv)

        screen_id = self.root.get_screen('main').ids.video_list

        for i in range(5):
            # Make a new image widget for each MDCard
            image = AsyncImage(
                source='https://static.hub.91mobiles.com/wp-content/uploads/2020/05/How-to-download-youtube-videos.jpg', size_hint=(1, .7), )
            card = MDCard(orientation='vertical', pos_hint={
                            'center_x': .5, 'center_y': .7}, size_hint=(.9, None), height=200)
            card.add_widget(image)
            card.add_widget(MDLabel(
                text='Phishing attacks are SCARY easy to do!! (let me show you!)', size_hint=(.6, .2), ))
            screen_id.add_widget(card)

    def build(self):
        return self.root

if __name__ == "__main__":
    Ytube().run()