Using local variables in a KV file

1,396 views
Skip to first unread message

Colin Brett

unread,
Aug 3, 2016, 4:03:11 PM8/3/16
to Kivy users support
Hi,

The app I'm working on needs to pass a variable set by a checkbox in the KV file back to the main Python program. The relevant section of the KV file is:

<SelectGenre>:
    GridLayout:
        cols: 2
        Label:
            text:'Fantasy'
        CheckBox:
            group: 'genre_group'
            on_active: root.fantasy_genre(*args)
            #:set genre 'fantasy'
        Label:
            text:'Sci-Fi'
        CheckBox:
            group: 'genre_group'
            on_active: root.scifi_genre(*args)
            #:set genre 'scifi'
        Label:
            text:'Cyberpunk'
        CheckBox:
            group: 'genre_group'
            on_active: root.cyberpunk_genre(*args)
            #:set genre 'cyberpunk'
        Label:
            text:'Wild West'
        CheckBox:
            group: 'genre_group'
            on_active: root.wildwest_genre(*args)
            #:set genre 'wildwest'
        Label:
            text:'Horror'
        CheckBox:
            group: 'genre_group'
            on_active: root.horror_genre(*args)
            #:set genre 'horror'
        Button:
            text:'Back'
            on_press: root.manager.current = 'welcome'
        Button:
            text:'Next'
#           on_press: root.manager.current = 'race'
            on_press: root.choose_race_screen(genre)

I want to pass the variable for the chosen genre into the following Python function:

 class SelectGenre(Screen):
#   pass
#self.manager.genre = ''

    def choose_race_screen(self,args):
        print (self)
        print (args)
        print (*args)
        race_display = args
        print ("Race display =", race_display)
        if race_display == 'fantasy':
            sm.current = 'race_fantasy'
        if race_display == 'scifi':
            sm.current = 'race_scifi'
        if race_display == 'cyberpunk':
            sm.current = 'race_cyberpunk'
        if race_display == 'wildwest':
            sm.current = 'race_wildwest'
        if race_display == 'horror':
            sm.current = 'race_horror'

The idea being, if a scifi genre is chosen, the races appropriate to that genre will be displayed next. What's happening is that no matter which genre I select, it always ends up as "horror".

Now, I think variables set with the #:set construct in the KV file are treated as global variables and that (presumably) the last option in the <SelectGenre> screen overrides all the others. Is this correct?

So the question is: how do I set a local variable in the KV file which can be successfully passed to the choose_race_screen function?

Please let me know if any further information is needed.

Regards,
Colin Brett

ZenCODE

unread,
Aug 3, 2016, 5:10:35 PM8/3/16
to Kivy users support
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, SlideTransition
from kivy.properties import StringProperty


class SelectGenre(Screen):
genre = StringProperty()

def choose_race_screen(self):
print("Race display =", "_".join(['race', self.genre]))
# sm.current = "_".join(['race', race])


class MainApp(App):
def build(self):
Builder.load_file('<your_kv_file>.kv')
return SelectGenre()

if __name__ == '__main__':

MainApp().run()

========================
'<your_kv_file>.kv'
========================

<SelectGenre>:
GridLayout:
cols: 2
Label:
text:'Fantasy'
CheckBox:
group: 'genre_group'
            on_active: root.genre = 'fantasy'

#:set genre 'fantasy'
Label:
text:'Sci-Fi'
CheckBox:
group: 'genre_group'
            on_active: root.genre = 'scifi'

#:set genre 'scifi'
Label:
text:'Cyberpunk'
CheckBox:
group: 'genre_group'
            on_active: root.genre = 'cyberpunk'

#:set genre 'cyberpunk'
Label:
text:'Wild West'
CheckBox:
group: 'genre_group'
            on_active: root.genre = 'wildwest'

#:set genre 'wildwest'
Label:
text:'Horror'
CheckBox:
group: 'genre_group'
            on_active: root.genre = 'horror'

#:set genre 'horror'
Button:
text:'Back'
on_press: root.manager.current = 'welcome'
Button:
text:'Next'
# on_press: root.manager.current = 'race'
            on_press: root.choose_race_screen()

Colin Brett

unread,
Aug 4, 2016, 6:14:48 AM8/4/16
to Kivy users support
Hi ZenCODE,

Your suggestions worked like a charm. Thank you very much.

Colin

PS: How can I +1 your post?


On Wednesday, August 3, 2016 at 9:03:11 PM UTC+1, Colin Brett wrote:

ZenCODE

unread,
Aug 4, 2016, 7:43:01 AM8/4/16
to Kivy users support
Glad it worked :-)

There is a star at the top left of the post, next to the first line.

ps. I should probably point out that 'on_active' will fire also for a deactivate, then the activate, so the above is not 100% optimal. You could have:

on_active: if args[1]: root.genre = "blah"

so that it only fires when the active state is True (args are the parameters passed to the 'on_active' event). But I really doubt that is an issue in this case...

Reply all
Reply to author
Forward
0 new messages