Search code examples
pythonkivykivy-language

Get access a variable inside a method from another class - Python and Kivy


I'm currently working with kivy to develop an application that will be printing numbers dinamically in several screens.

Right now is printing values from one screen but I also have to show values in other two screens, the problem is that I'm calling a method from one class to run continously in time and update the variable values and I would like to consult or get access to those variables from that method in other class to print them in the other screens, each class represents one screen so it's necessary their presence in code.

I would like to know if this is possible and how could I implement a solution to do it.

Let me share you my piece of code, it's very large so I would paste only relevant code:

gui.py

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.properties import ObjectProperty, StringProperty, NumericProperty
from kivy.uix.gridlayout import GridLayout
from kivy.clock import Clock

# Creating dynamic variables
class Show_Val(Screen):
    timer_update = NumericProperty(0)
    dist_travel = NumericProperty(0)
    average_mph = NumericProperty(0)
    temp = NumericProperty(0)
    dist_travel_2 = NumericProperty(0)

# screen 1: this is working ok
class Main_Screen(Screen):
    update_val = Show_Val()

    def update(self, dt):
        # these corresponds to the screen 1, their are currently working
        self.update_val.timer_update += 1
        self.update_val.dist_travel += 1 
        self.update_val.average_mph += 1

        # temp variable would be printed in screen 2: Input_Screen
        self.update_val.temp += 1

        # and dist_travel_2 will be printed in screen 3: Route_Screen
        self.update_val.dist_travel_2 += 1


# screen 2: here I need to get access to self.update_val.temp      
class Input_Screen(Screen):
    pass

# screen 3: here I need to get access to self.update_val.temp   
class Route_Screen(Screen):
    pass

# screen 0 or master screen management, it's just for reference
class Screen_Management(ScreenManager):
    pass

presentation = Builder.load_file("gui.kv")

class guiApp(App):
    def build(self):
        main = Main_Screen()

        # this call is my "loop" and is updating the variables at 50hz
        # frequency, I tried to call differently functions like this one
        # but with no success.
        Clock.schedule_interval(main.update, 1.0/50.0)
        return presentation

guiApp().run()

gui.kv

Screen_Management:
    id: screen_management
    transition: FadeTransition()
    Main_Screen:
        id: main_screen
        name: "main_screen_name"
        manager: screen_management
    Input_Screen:
        id: tire_setup_screen_id
        name: "tire_setup_screen_name"
        manager: screen_management
    Route_Screen:
        name: "route_input_screen_name"

##############################################################
##############################################################

# Screen 1: Main Screen
# working ok
<Main_Screen>:
    canvas:
        Color:
            rgb: [.30, .30, .30]
        Rectangle:
            pos: self.pos
            size: self.size

    BoxLayout:
        orientation: 'vertical'
        Button:
            id: timer_indicator
            background_disabled_down: ('0.00.00,000')
            background_color: .52, .52, .52, 1
            bold: 1
            color: .0078,.67,.69,1
            font_size: 100
            text: str(root.update_val.timer_update)
            #text: root.update_val.test
            pos_hint: {'x': .2}
            size_hint: [.8, 1]


        Button:
            background_color: .52, .52, .52, 1
            bold: 1
            color: .0078,.67,.69,1
            font_size: 100
            text: str(root.update_val.dist_travel)
            pos_hint: {'x': .2}
            size_hint: [.8, 1]
        Button:
            background_color: .52, .52, .52, 1
            bold: 1
            color: .0078,.67,.69,1
            font_size: 100
            text: str(root.update_val.average_mph)
            pos_hint: {'x': .2}
            size_hint: [.8, 1]

    Button:
        background_color: .52, .52, .52, 1
        bold: 1
        color: .0078,.67,.69,1
        size_hint: .2, 1
        pos_hint: {"x": 0, "center_y": .5}
        on_release: app.root.current = "tire_setup_screen_name"
        text: " INPUTS "
        font_size: 30

##############################################################
##############################################################

# Screen 2: Input Screen
# I will need to print self.update_val.temp value in this creen

<Input_Screen>:
    canvas:
        Color:
            rgb: [.30, .30, .30]
        Rectangle:
            pos: self.pos
            size: self.size
    Button:
        background_color: .52, .52, .52, 1
        bold: 1
        color: .0078,.67,.69,1
        font_size: 30
        size_hint: 0.2, .5
        text: "MAIN"
        pos_hint: {'x':0, 'y': 0}
        on_release: app.root.current = "main_screen_name"
    Button:
        background_color: .52, .52, .52, 1
        bold: 1
        color: .0078,.67,.69,1
        font_size: 30
        size_hint: .2, .5
        text: "ROUTES"
        pos_hint: {'x':0, 'y': .5}
        on_release: app.root.current = "route_input_screen_name"  

    GridLayout:
        cols: 2
        pos: (205,150)
        size_hint: (.8, .75)

        Button:
            background_color: .52, .52, .52, 1
            bold: 1
            color: .0078,.67,.69,1
            font_size: 30
            text: "     TIRE\nTEMP (°C)"
            size_hint_x: None
            width: 150
        Button:
            background_color: .52, .52, .52, 1
            bold: 1
            color: .0078,.67,.69,1
            font_size: 100
            text: "000.000" # self.update_val.temp value it will be here

##############################################################
##############################################################

# Screen 3: Route Screen
# self.update_val.dist_travel_2 will be printed in this screen
<Route_Screen>:
    canvas:
        Color:
            rgb: [.30, .30, .30]
        Rectangle:
            pos: self.pos
            size: self.size

    Button:
        background_color: .52, .52, .52, 1
        bold: 1
        color: .0078,.67,.69,1
        font_size: 30
        size_hint: 0.2, .5
        text: "INPUTS"
        pos_hint: {'x':0, 'y': 0}
        on_release: app.root.current = "tire_setup_screen_name"

    BoxLayout:
        orientation: 'vertical'
        Button:
            background_color: .52, .52, .52, 1
            bold: 1
            color: .0078,.67,.69,1
            font_size: 50
            text: "000.000 MPH" # self.update_val.dist_travel_2 value 
            pos_hint: {'x': .2}
            size_hint: [.8, 1]

Thanks for your time and I hope that you could help me to solve this issue.

How can I access to variables from one method in other class?


Solution

  • Use Kivy ObjectProperty to hook up to the screen ids. Please refer to the example below for details.

    Snippets

    Python Script

    class Screen_Management(ScreenManager):
        main_screen = ObjectProperty(None)
        input_screen = ObjectProperty(None)
        route_screen = ObjectProperty(None)
    
    ...
    
    class Main_Screen(Screen):
        update_val = Show_Val()
    
        def update(self, dt):
            # these corresponds to the screen 1, their are currently working
            self.update_val.timer_update += 1
            self.update_val.dist_travel += 1
            self.update_val.average_mph += 1
    
            # temp variable would be printed in screen 2: Input_Screen
            self.update_val.temp += 1
            self.manager.input_screen.access_update_val(self.update_val)
            self.manager.route_screen.access_update_val(self.update_val)
    
            # and dist_travel_2 will be printed in screen 3: Route_Screen
            self.update_val.dist_travel_2 += 1
    

    kv file

    <Screen_Management>:
        id: screen_management
        main_screen: main_screen
        input_screen: tire_setup_screen_id
        route_screen: route_screen
        transition: FadeTransition()
        Main_Screen:
            id: main_screen
            name: "main_screen_name"
            manager: screen_management
        Input_Screen:
            id: tire_setup_screen_id
            name: "tire_setup_screen_name"
            manager: screen_management
        Route_Screen:
            id: route_screen
            name: "route_input_screen_name"
    

    Example

    gui2.py

    from kivy.app import App
    from kivy.uix.screenmanager import ScreenManager, Screen
    from kivy.properties import ObjectProperty, NumericProperty
    from kivy.clock import Clock
    
    
    # Creating dynamic variables
    class Show_Val(Screen):
        timer_update = NumericProperty(0)
        dist_travel = NumericProperty(0)
        average_mph = NumericProperty(0)
        temp = NumericProperty(0)
        dist_travel_2 = NumericProperty(0)
    
    
    # screen 1: this is working ok
    class Main_Screen(Screen):
        update_val = Show_Val()
    
        def update(self, dt):
            # these corresponds to the screen 1, their are currently working
            self.update_val.timer_update += 1
            self.update_val.dist_travel += 1
            self.update_val.average_mph += 1
    
            # temp variable would be printed in screen 2: Input_Screen
            self.update_val.temp += 1
            self.manager.input_screen.access_update_val(self.update_val)
            self.manager.route_screen.access_update_val(self.update_val)
    
            # and dist_travel_2 will be printed in screen 3: Route_Screen
            self.update_val.dist_travel_2 += 1
    
    
    # screen 2: here I need to get access to self.update_val.temp
    class Input_Screen(Screen):
        def access_update_val(self, obj):
            print("Input_Screen: update_val.temp={}".format(obj.temp))
    
    
    # screen 3: here I need to get access to self.update_val.temp
    class Route_Screen(Screen):
        def access_update_val(self, obj):
            print("Route_Screen: update_val.temp={}".format(obj.temp))
    
    
    # screen 0 or master screen management, it's just for reference
    class Screen_Management(ScreenManager):
        main_screen = ObjectProperty(None)
        input_screen = ObjectProperty(None)
        route_screen = ObjectProperty(None)
    
    
    class gui2App(App):
        def build(self):
            sm = Screen_Management()
    
            # this call is my "loop" and is updating the variables at 50hz
            # frequency, I tried to call differently functions like this one
            # but with no success.
            Clock.schedule_interval(sm.main_screen.update, 1.0/50.0)
            return sm
    
    
    if __name__ == "__main__":
        gui2App().run()
    

    gui2.kv

    #:kivy 1.10.0
    #:import FadeTransition kivy.uix.screenmanager.FadeTransition
    
    <Screen_Management>:
        id: screen_management
        main_screen: main_screen
        input_screen: tire_setup_screen_id
        route_screen: route_screen
        transition: FadeTransition()
        Main_Screen:
            id: main_screen
            name: "main_screen_name"
            manager: screen_management
        Input_Screen:
            id: tire_setup_screen_id
            name: "tire_setup_screen_name"
            manager: screen_management
        Route_Screen:
            id: route_screen
            name: "route_input_screen_name"
    
    ##############################################################
    ##############################################################
    
    # Screen 1: Main Screen
    # working ok
    <Main_Screen>:
        canvas:
            Color:
                rgb: [.30, .30, .30]
            Rectangle:
                pos: self.pos
                size: self.size
    
        BoxLayout:
            orientation: 'vertical'
            Button:
                id: timer_indicator
                background_disabled_down: ('0.00.00,000')
                background_color: .52, .52, .52, 1
                bold: 1
                color: .0078,.67,.69,1
                font_size: 100
                text: str(root.update_val.timer_update)
                #text: root.update_val.test
                pos_hint: {'x': .2}
                size_hint: [.8, 1]
    
    
            Button:
                background_color: .52, .52, .52, 1
                bold: 1
                color: .0078,.67,.69,1
                font_size: 100
                text: str(root.update_val.dist_travel)
                pos_hint: {'x': .2}
                size_hint: [.8, 1]
            Button:
                background_color: .52, .52, .52, 1
                bold: 1
                color: .0078,.67,.69,1
                font_size: 100
                text: str(root.update_val.average_mph)
                pos_hint: {'x': .2}
                size_hint: [.8, 1]
    
        Button:
            background_color: .52, .52, .52, 1
            bold: 1
            color: .0078,.67,.69,1
            size_hint: .2, 1
            pos_hint: {"x": 0, "center_y": .5}
            on_release: app.root.current = "tire_setup_screen_name"
            text: " INPUTS "
            font_size: 30
    
    ##############################################################
    ##############################################################
    
    # Screen 2: Input Screen
    # I will need to print self.update_val.temp value in this creen
    
    <Input_Screen>:
        canvas:
            Color:
                rgb: [.30, .30, .30]
            Rectangle:
                pos: self.pos
                size: self.size
        Button:
            background_color: .52, .52, .52, 1
            bold: 1
            color: .0078,.67,.69,1
            font_size: 30
            size_hint: 0.2, .5
            text: "MAIN"
            pos_hint: {'x':0, 'y': 0}
            on_release: app.root.current = "main_screen_name"
        Button:
            background_color: .52, .52, .52, 1
            bold: 1
            color: .0078,.67,.69,1
            font_size: 30
            size_hint: .2, .5
            text: "ROUTES"
            pos_hint: {'x':0, 'y': .5}
            on_release: app.root.current = "route_input_screen_name"
    
        GridLayout:
            cols: 2
            pos: (205,150)
            size_hint: (.8, .75)
    
            Button:
                background_color: .52, .52, .52, 1
                bold: 1
                color: .0078,.67,.69,1
                font_size: 30
                text: "     TIRE\nTEMP (°C)"
                size_hint_x: None
                width: 150
            Button:
                background_color: .52, .52, .52, 1
                bold: 1
                color: .0078,.67,.69,1
                font_size: 100
                text: "000.000" # self.update_val.temp value it will be here
    
    ##############################################################
    ##############################################################
    
    # Screen 3: Route Screen
    # self.update_val.dist_travel_2 will be printed in this screen
    <Route_Screen>:
        canvas:
            Color:
                rgb: [.30, .30, .30]
            Rectangle:
                pos: self.pos
                size: self.size
    
        Button:
            background_color: .52, .52, .52, 1
            bold: 1
            color: .0078,.67,.69,1
            font_size: 30
            size_hint: 0.2, .5
            text: "INPUTS"
            pos_hint: {'x':0, 'y': 0}
            on_release: app.root.current = "tire_setup_screen_name"
    
        BoxLayout:
            orientation: 'vertical'
            Button:
                background_color: .52, .52, .52, 1
                bold: 1
                color: .0078,.67,.69,1
                font_size: 50
                text: "000.000 MPH" # self.update_val.dist_travel_2 value
                pos_hint: {'x': .2}
                size_hint: [.8, 1]
    

    Output

    enter image description here