KivyMD: как мне автоматически отобразить MDList, сгенерированный в файле python

#python #kivy #kivymd

#python #kivy #kivymd

Вопрос:

Спасибо, что взглянули. Я совершенно новичок в Kivy / KivyMD / programming, и есть что-то фундаментальное, чего я просто не понимаю между кодом python и кодом kv.

Я создаю простое приложение, которое использует ScreenManager для переключения между двумя экранами. На каждом экране я планирую иметь динамически сгенерированный список с данными из базы данных.

Я могу добавлять статические списки и другие виджеты, помещая их в файл kv. Но, похоже, я не могу понять, как создать / обновить данные в классе в файле python и связать их с идентификатором файла kv.

В следующем коде программа работает, и я вставил в нее кнопку, которая успешно генерирует список, но цель состоит в том, чтобы не иметь кнопки и чтобы список генерировался автоматически при запуске приложения.

Я добавил несколько комментариев с тем, что я пробовал. Я использую неправильные имена переменных или делаю что-то принципиально неправильное?

[main.py файл python]

 from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivymd.uix.list import OneLineListItem


class FirstWindow(Screen):
    print('This prints automatically when App launches')

    # But adding widgets doesn't happen automatically
    # I tried variations but the variable is always not defined
    #self.ids.list_one.add_widget(OneLineListItem(text='List Item 1'))
    #root.ids.list_one.add_widget(OneLineListItem(text='List Item 1'))
    #ids.list_one.add_widget(OneLineListItem(text='List Item 1'))

    # This function works when called from a button
    def button_push(self):
        for i in range (20):
            self.ids.list_one.add_widget(OneLineListItem(text=f'List Item {i}'))

class SecondWindow(Screen):
    pass

class WindowManager(ScreenManager):
    pass

class MultiscreenApp(MDApp):
    def build(self):
        return Builder.load_file('Multiscreen.kv')

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

[Файл Multiscreen.kv]

 WindowManager:
    FirstWindow:
        name: 'firstwindow'
    SecondWindow:
        name: 'secondwindow'


<FirstWindow>:
    BoxLayout:
        orientation: 'vertical'

        MDToolbar:
            title: 'SCREEN 1'

        Button:
            text: 'List maker button'
            on_release: root.button_push()

        ScrollView:
            MDList:
                id: list_one

        MDFloatingActionButton:
            elevation: 8
            icon: 'plus'
            pos_hint: {'center_x': .5}
            on_press:
                app.root.current = 'secondwindow'
                root.manager.transition.direction = 'left'

<SecondWindow>:
    BoxLayout:
        orientation: 'vertical'

        MDToolbar:
            title: 'SCREEN 2'

        ScrollView:
            MDList:
                id: list_two

        MDRaisedButton:
            text: 'Go Back'
            on_release:
                app.root.current = 'firstwindow'
                root.manager.transition.direction = 'right'
  

Ответ №1:

Вы можете добавить __init___ метод с Clock.schedule_once , чтобы инициировать создание списка. Ниже приведен измененный код. Я не изменил остальной код, просто добавил две функции для отображения автоматического создания списка.

 from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivymd.uix.list import OneLineListItem
from kivy.clock import Clock

class FirstWindow(Screen):
    print('This prints automatically when App launches')
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        Clock.schedule_once(self.create_list)
        
    def create_list(self, *args):
        for i in range (20):
            self.ids.list_one.add_widget(OneLineListItem(text=f'List Item {i}'))
    # But adding widgets doesn't happen automatically
    # I tried variations but the variable is always not defined
    #self.ids.list_one.add_widget(OneLineListItem(text='List Item 1'))
    #root.ids.list_one.add_widget(OneLineListItem(text='List Item 1'))
    #ids.list_one.add_widget(OneLineListItem(text='List Item 1'))

    # This function works when called from a button
    def button_push(self):
        for i in range (20):
            self.ids.list_one.add_widget(OneLineListItem(text=f'List Item {i}'))

class SecondWindow(Screen):
    pass

class WindowManager(ScreenManager):
    pass

class MultiscreenApp(MDApp):
    def build(self):
        return Builder.load_file('Multiscreen.kv')

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

Комментарии:

1. Это сделало это. Большое вам спасибо. Я все еще не совсем понимаю суперфункцию. Я понимаю, что такое наследование, но фрагменты еще не до конца прояснились в моем мозгу. Я буду продолжать изучать.

2. Перегруженная super функция необходима в __init__ методе, чтобы избежать ошибки сегментации.

3. как добавить идентификатор каждого элемента списка?

Ответ №2:

 class FirstWindow(Screen):
    def on_enter(self, *args):
        """Event fired when the screen is displayed: the entering animation is
        complete."""

        def on_enter(interval):
            for i in range (20):
                self.ids.list_one.add_widget(OneLineListItem(text=f'List Item {i}'))

        Clock.schedule_once(on_enter)
  

Комментарии:

1. Спасибо. Это тоже работает. Вы предоставили мне варианты и помогли мне немного лучше понять общую картину.