KivyMD sharing variables/data through Screens

537 views Asked by At

I'm currently building a small program that converts an Excel sheet into a JSON format. I want that every time a change or update is made, the excel file gets updated with a Login and Date information of the person who made the change. I have created Two screens using KivyMD, one for the login data and another one for the excel functionality. My current issue is that I want to acquire the login information from the previous screen, but I'm having a hard time understanding how to get the data. I have tried to create a "login" variable within my "Update" screen referencing the id from the "Log" screen by using this line I found on a previous post: "login = self.manager.screens[1].ids.login.text"

But that line is giving me the following error : "
login = self.manager.screens[1].ids.login.text File "kivy\properties.pyx", line 863, in kivy.properties.ObservableDict.getattr AttributeError: 'super' object has no attribute 'getattr' "

I'm very new to KivyMD and I'm pretty sure that there is something over here that I'm not seeing or just missing. I would appreciate any help given.

Here is my .py file:

import os.path
from kivymd.app import MDApp
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.lang import Builder
from kivymd.uix.button import MDFlatButton
from kivymd.uix.dialog import MDDialog
from helpers import screen_helper_2
from kivy.core.window import Window
from datetime import datetime
import json
import functions as function

Window.size = (400, 500)


# AlbacoreLog Screen Fully Functional
class AlbacoreLogScreen(Screen):
    def show_login(self, *args):
        close_button = MDFlatButton(text='Close', on_release=self.close_dialog)
        if self.ids.login.text is "":
            check_string = 'Please enter Login or Name'
            self.dialog = MDDialog(text=check_string,
                                   size_hint=(0.7, 1),
                                   buttons=[close_button])
            self.dialog.open()

        else:
            self.manager.current = 'function'

    def close_dialog(self, obj):
        self.dialog.dismiss()


class AutoUpdateScreen(Screen):
    def albacorize_update(self, *args):
        def close_ext(*args):
            dialog_ext.dismiss()

        def close_ext_2(*args):
            dialog_5.dismiss()

        def close_update(*args):
            dialog_update.dismiss()

        close_button_ext_2 = MDFlatButton(text='Close', on_release=close_ext_2)
        close_button_ext = MDFlatButton(text='Close', on_release=close_ext)
        close_button_update = MDFlatButton(text='Close', on_release=close_update)

        if self.ids.change.text is "":
            dialog_update = MDDialog(text='Also, make sure to add your update',
                                     size_hint=(0.7, 1),
                                     buttons=[close_button_update])
            dialog_update.open()

            self.back_to_update()

        if self.ids.ms.text is "":
            dialog_ext = MDDialog(text='Please enter Master Sheet name and extension',
                                  size_hint=(0.7, 1),
                                  buttons=[close_button_ext])
            dialog_ext.open()

            self.back_to_update()
        elif type(self.ids.ms.text) is str:
            ms = self.ids.ms.text
            update = self.ids.change.text
            if os.path.isfile(ms):
                login = self.manager.screens[1].ids.login.text
                now = datetime.now()
                time_date = now.strftime("%d/%m/%Y %H:%M:%S")
                print("File exist")

                q_and_a_section = function.question_answer_build(ms)
                node_section = function.section_build(ms)
                function.updates(ms, login, time_date, update)  ##I want to pass the login data to a different module on my program in order to build the new excel sheet.

                
            else:
                print("File not exist")
                dialog_5 = MDDialog(text='MS does not have extension or is not in current root folder',
                                    size_hint=(0.7, 1),
                                    buttons=[close_button_ext_2])
                dialog_5.open()
                self.manager.current = 'msautomap'

    def back_to_function(self, *args):
        self.manager.current = 'function'

    def back_to_update(self, *args):
        self.manager.current = 'msautoupdate'


sm = ScreenManager()
sm.add_widget(AlbacoreLogScreen(name='log'))
sm.add_widget(AutoUpdateScreen(name='msautoupdate'))


class AlbacorizerApp(MDApp):
    def build(self):
        self.theme_cls.primary_palette = "Yellow"
        self.theme_cls.primary_hue = "A700"
        self.theme_cls.theme_style = "Dark"
        screen = Builder.load_string(screen_helper_2)

        return screen


AlbacorizerApp().run()

And here is my .kv file:

screen_helper_2 = """
Screen:
    NavigationLayout:
        ScreenManager:
            AlbacoreLogScreen:
            AutoUpdateScreen:

<AlbacoreLogScreen>:
    name: 'log'
    BoxLayout:
        orientation: 'vertical'
        MDToolbar:
            title: 'Albacorizer Log'
            left_action_items: [["lighthouse", lambda x: nav_drawer.toggle_nav_drawer()]]
            elevation: 10

        Widget:

        MDTextField:
            id: login
            hint_text: "Enter login"
            helper_text: "or enter name"
            helper_text_mode: "on_focus"
            icon_right: "lighthouse-on"
            icon_right_color: app.theme_cls.primary_color
            pos_hint:{'center_x':0.5, 'center_y':0.7}
            size_hint_x: None
            size_hint_y: None
            width: 300

        MDRectangleFlatButton:
            text: 'Go !'
            pos_hint: {'center_x':0.5,'center_y':0.4}
            on_release:
                root.show_login()
                

        Widget:
    
<AutoUpdateScreen>:
    name: 'msautoupdate'
    BoxLayout:
        orientation: 'vertical'
        MDToolbar:
            title: 'MS Automap Update'
            left_action_items: [["lighthouse", lambda x: nav_drawer.toggle_nav_drawer()]]
            elevation: 10

        Widget:

        MDTextField:
            id: ms
            hint_text: "What is the MS name and extension?"
            helper_text: "don't forget the extension"
            helper_text_mode: "on_focus"
            icon_right: "lighthouse-on"
            icon_right_color: app.theme_cls.primary_color
            pos_hint:{'center_x': 0.5, 'center_y': 0.5}
            size_hint_x: None
            width: 300
            
        MDTextFieldRect:
            id: change
            hint_text: "Summary of changes to MS"
            mode: "rectangle"
            pos_hint:{'center_x': 0.5, 'center_y': 0.5}
            size_hint_x: None
            width: 200
            height: "100dp"
                    
        Widget:
        
        MDRectangleFlatButton:
            text: 'Albacorize !'
            pos_hint: {'center_x':0.5,'center_y':0.2}
            on_release:
                root.albacorize_update()

        Widget:
        
        MDRectangleFlatButton:
            text: 'Back'
            pos_hint: {'center_x':0.5,'center_y':0.3}
            on_release:
                root.back_to_function()
                root.manager.transition.direction = 'right'
        
        Widget:        
"""
1

There are 1 answers

1
John Anderson On

Try changing:

login = self.manager.screens[1].ids.login.text

to:

login = self.manager.get_screen('log').ids.login.text

Using self.manager.screens[1] makes your code depend on the order of Screens in the screens list (and [1] is the wrong one). Using get_screen('log') makes your code independent of the order of the Screens (and gets the correct one).