简体   繁体   English

如何在 KivyMD 屏幕之间传递参数?

[英]How do I pass an argument between KivyMD screens?

When going from the first screen to the second screen, I want to pass a variable as an argument so that kivyMD can update the second screen from text stored in an excel file.当从第一个屏幕转到第二个屏幕时,我想传递一个变量作为参数,以便 kivyMD 可以从存储在 excel 文件中的文本更新第二个屏幕。 The following is a skeleton of my app's functionality:以下是我的应用程序功能的框架:

The user reaches Screen 1 thru the navigation drawer in KivyMD, screen 1 presents the user with two options on two small clickable MDCards:用户通过 KivyMD 中的导航抽屉到达屏幕 1,屏幕 1 在两个可点击的小 MDCard 上为用户提供两个选项:

  • "Change text to 1" “将文本更改为 1”
  • "Change text to 2" “将文本更改为 2”

After clicking on one of these, the app switches to screen 2 with a single big MDCard, the text on this MDCard should change to reflect the option the user chose.单击其中之一后,应用程序将切换到带有单个大 MDCard 的屏幕 2,此 MDCard 上的文本应更改以反映用户选择的选项。

However, kivy is pulling the text that is to be displayed on the big MDCard from an excel file.然而,kivy 正在从一个 excel 文件中提取要显示在大 MDCard 上的文本。 The variable that I want to pass from screen 1 to screen 2 is simply a number (1 or 2) that will tell kivy which row in the excel file it should pull the text from我想从屏幕 1 传递到屏幕 2 的变量只是一个数字(1 或 2),它会告诉 kivy 它应该从 excel 文件中的哪一行提取文本

If the user clicks "Change text to 1" then the first screen should pass "1" as the argument row_x to the function def change_text() (see screen 2 .py) so that the text in row 1 of excel can be displayed on the second screen.如果用户单击“将文本更改为 1”,则第一个屏幕应将“1”作为参数row_x传递给函数def change_text() (请参阅屏幕 2 .py),以便可以在 excel 的第 1 行中显示文本第二个屏幕。 How can I achieve this?我怎样才能做到这一点?

I have 4 files in total;我总共有 4 个文件; 3 are .py files (one for the main app, one for screen 1, and one for screen 2), and the excel file 3 个是 .py 文件(一个用于主应用程序,一个用于屏幕 1,一个用于屏幕 2)和 excel 文件

NOTE: in the code below, Screen 1 & 2 are called Element 1 & 2 respectfully注意:在下面的代码中,屏幕 1 和 2 分别称为元素 1 和 2

Main.py:主要.py:

from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
from kivymd.app import MDApp
from element_1 import element_1_screen
from element_2 import element_2_screen

MainNavigation = '''
<ContentNavigationDrawer>:
    ScrollView:
        MDList:
            OneLineListItem:
                text: 'Go to Element 1'
                on_press:
                    root.nav_drawer.set_state("close")
                    root.screen_manager.current = "go_to_element_1_screen"

Screen:
    MDToolbar:
        id: toolbar
        pos_hint: {"top": 1}
        elevation: 10
        left_action_items: [["menu", lambda x: nav_drawer.set_state("open")]]
    MDNavigationLayout:
        x: toolbar.height
        ScreenManager:
            id: screen_manager
            Screen:
                name: "words_nav_item"
            element_1_screen:
                name: "go_to_element_1_screen"
            element_2_screen:
                name: "go_to_element_2_screen"

        MDNavigationDrawer:
            id: nav_drawer
            ContentNavigationDrawer:
                screen_manager: screen_manager
                nav_drawer: nav_drawer
'''


class ContentNavigationDrawer(BoxLayout):
    screen_manager = ObjectProperty()
    nav_drawer = ObjectProperty()


class mainApp(MDApp):
    def build(self):
        self.theme_cls.primary_palette = "Red"
        return Builder.load_string(MainNavigation)


mainApp().run()

Screen 1 / Element 1屏幕 1 / 元素 1

from kivy.lang import Builder
from kivymd.uix.screen import MDScreen

element_1_contents = '''
<element_1_screen>:
    MDGridLayout:
        rows: 2
        size: root.width, root.height
        pos_hint: {"center_x": .8, "center_y": .2}
        spacing: 40
        MDCard:
            orientation: 'vertical'
            size_hint: None, None
            size: "360dp", "120dp"
            ripple_behavior: True
            on_release:
                root.manager.current = "go_to_element_2_screen" 
            MDLabel:
                id: LabelTextID
                text: "Change Text to 1"
                halign: 'center'
    
        MDCard:
            orientation: 'vertical'
            size_hint: None, None
            size: "360dp", "120dp"
            ripple_behavior: True
            on_release:
                root.manager.current = "go_to_element_2_screen" 
            MDLabel:
                id: LabelTextID
                text: "Change Text to 2"
                halign: 'center'
                
        
'''

class element_1_screen(MDScreen):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        Builder.load_string(element_1_contents)

Screen 2 / Element 2屏幕 2 / 元素 2

from kivy.lang import Builder
from kivymd.uix.screen import MDScreen
import openpyxl

element_2_contents = '''
<element_2_screen>:
    MDCard:
        orientation: 'vertical'
        size_hint: None, None
        size: "360dp", "360dp"
        pos_hint: {"center_x": .5, "center_y": .5}
        ripple_behavior: True
        focus_behavior: True
        on_release: root.manager.current = "go_to_element_1_screen"

        MDLabel:
            id: TextID
            text: "NOTHING HAS CHANGED"
            halign: 'center'

        MDLabel:
            text: "(Click here to return)"
            halign: 'center'
            
'''

class element_2_screen(MDScreen):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        path = "data.xlsx"
        self.wb_obj = openpyxl.load_workbook(path)
        self.sheet_obj = self.wb_obj.active
        Builder.load_string(element_2_contents)

    def change_text(self, row_x=0):
        row_number = self.sheet_obj.cell(row_x, column=1)
        self.ids.TextID.text = str(row_number.value)

And the excel file only has two entries in Column A:并且excel文件在A列中只有两个条目:

Row 1: You have chosen 1
Row 2: You have chosen 2

I found the answer and now it works flawlessly.我找到了答案,现在它完美无缺。 Someone over on Reddit (u/Username_RANDINT) helped me, this is what they said: Reddit 上有人 (u/Username_RANDINT) 帮助了我,他们是这样说的:

The ScreenManager has a get_screen() method. ScreenManager 有一个get_screen()方法。 You could use it to get the instance of the second screen and call the change_text() method on that.您可以使用它来获取第二个屏幕的实例并在其上调用change_text()方法。 In the same place where you switch screens, add another line:在切换屏幕的同一个地方,添加另一行:

    on_release:
        root.manager.current = "go_to_element_2_screen"
        root.manager.get_screen("go_to_element_2_screen").change_text(1)

Then the same for the other card, just pass in 2 instead of 1.然后对另一张卡也一样,只需传入 2 而不是 1。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM