Как я могу изменить экран, используя нижний лист в kivymd?

#python #kivy #kivymd

#python #kivy #kivymd

Вопрос:

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

app.py

 from kivymd.app import MDApp
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.lang import Builder
from main_screen_str import helper_string
from kivy.core.window import Window
from kivymd.toast import toast
from kivymd.uix.bottomsheet import MDGridBottomSheet

Window.size = (300, 500)


class MainScreen(Screen):
    pass


class SettingsScreen(Screen):
    pass


class AboutScreen(Screen):
    pass


class MainApp(MDApp):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.sm = ScreenManager()
        self.sm.add_widget(MainScreen(name="main_screen"))
        self.sm.add_widget(SettingsScreen(name="settings_screen"))
        self.sm.add_widget(AboutScreen(name="about_screen"))

        self.main_str = Builder.load_string(helper_string)

    def build(self):
        screen = Screen()
        screen.add_widget(self.main_str)
        return screen

    def callback_for_menu_items(self, *args):
        if args[0] == 'Home':
            toast(args[0])
            self.sm.current = "main_screen"

        if args[0] == 'Settings':
            toast(args[0])
            self.sm.current = "settings_screen"

        if args[0] == 'About':
            toast(args[0])
            self.sm.current = "about_screen"

    def show_example_grid_bottom_sheet(self):
        self.bottom_sheet_menu = MDGridBottomSheet()

        data = {
            "Home": "home",
            "Settings": "settings",
            "About": "information-outline",
        }
        for item in data.items():
            self.bottom_sheet_menu.add_item(
                item[0],
                lambda x, y=item[0]: self.callback_for_menu_items(y),
                icon_src=item[1],
            )
        self.bottom_sheet_menu.open()


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

  

Эта строка конструктора для создания экрана.
Есть ли лучшее решение для этого?

строка конструктора

 helper_string = """
ScreenManager:
    MainScreen:
    SettingsScreen:
    AboutScreen:

<MainScreen>:
    name: 'main_screen'

    MDIconButton:
        icon: "menu"
        theme_text_color: "Custom"
        text_color: 1,0,0,1
        on_press: app.show_example_grid_bottom_sheet()
  
<SettingsScreen>:
    name: 'settings_screen'
    
<AboutScreen>:
    name: 'about_screen'      
"""

  

Ответ №1:

В вашем __init__() методе App вы строите self.sm из строк:

     self.sm = ScreenManager()
    self.sm.add_widget(MainScreen(name="main_screen"))
    self.sm.add_widget(SettingsScreen(name="settings_screen"))
    self.sm.add_widget(AboutScreen(name="about_screen"))
  

Но self.sm не используется как часть вашего графического интерфейса. Таким образом, ваши изменения в self.sm не влияют на ваш графический интерфейс. Строка, следующая за этим:

 self.main_str = Builder.load_string(helper_string)
  

в основном делает то же самое, что и предыдущие строки.

Затем в вашем build() методе вы создаете новый Screen и добавляете self.main_str в качестве дочернего элемента этого Screen .

Хотя у вас может быть ScreenManager дочерний элемент Screen , в вашем опубликованном примере это, похоже, не служит какой-либо цели.

Вот измененная версия части MainApp , которая, я думаю, будет делать то, что вы хотите:

 class MainApp(MDApp):
    # def __init__(self, **kwargs):
    #     super().__init__(**kwargs)
    #     self.sm = ScreenManager()
    #     self.sm.add_widget(MainScreen(name="main_screen"))
    #     self.sm.add_widget(SettingsScreen(name="settings_screen"))
    #     self.sm.add_widget(AboutScreen(name="about_screen"))
    #
    #     self.main_str = Builder.load_string(helper_string)

    def build(self):
        self.sm = Builder.load_string(helper_string)
        return self.sm
        # screen = Screen()
        # screen.add_widget(self.main_str)
        # return screen
  

Приведенный выше код значительно упрощает build() метод, устраняет __init__() метод и теперь self.sm фактически является частью графического интерфейса.

Обратите внимание, что когда вы загружаете kv строку, в которой есть корневой узел с Builder.load_string() , этот корневой узел создается и возвращается. Строки в вашей kv строке:

 ScreenManager:
    MainScreen:
    SettingsScreen:
    AboutScreen:
  

в результате создается ScreenManager экземпляр вместе с тремя дочерними элементами, перечисленными для него, поэтому код в вашем __init__() методе дублировал это.