master
master

Reputation: 17

How to update label text in .kv using properties in .py?

I want to update values in my class MainHero using button in .kv and based on attribute nick in my class I need to update label in .kv. I need to handle this automatically, because many other attributes will be generated automatically so labels need to be updated. Here is part of my code:

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import *
from kivy.lang import Builder
from kivy.clock import Clock


class MainHero():
     def __init__(self):
          self.nick = "Player"

class FightScreen(Screen):
    def __init__(self, **kwargs):
        super(FightScreen, self).__init__(**kwargs)
        self.af_init = Clock.create_trigger(self._init)
        self.af_init()

    def _init(self, dt):
         self.app = App.get_running_app()
    
    def rename(self):
        self.app.main_hero.nick = "Renamed"


class ScreenManagement(ScreenManager):
    pass



class Design(App):
    def __init__(self, **kwargs):
        super(Design, self).__init__(**kwargs)
        self.main_hero = MainHero() # Tried main_hero = MainHero() too
        self.val = StringProperty(self.main_hero.nick)  # string

    # Construct app
    def build(self):
        # design constructor
        kv = Builder.load_file('AppDesign.kv')
        return kv

if __name__ == "__main__":
    Design().run()
# Using kv 2.0
ScreenManagement:
    id: screen_manager
    FightScreen:
        name: 'FightScreen'
        manager: screen_manager
        id: fight_screen

<FightScreen>

FloatLayout:
     Label:
          text: app.val
          size_hint: .2, .2
          pos_hint: {'center_x': .5, 'center_y': .35}
     Button:
          size_hint: .2, .2
          pos_hint: {'center_x': .5, 'center_y': .5}
          on_press:
               root.rename()
          

It is probably possible through properties/EventDispetcher. Reference app.val in many cases I tried is something like <StringProperty name=>. I tried using (maybe wrong)

class Aaa(EventDispetcher); apply_property(**kwargs) I want to do that with ObjectProperty too, it's different I think and I have no idea how to do it.

Edit:

     def rename(self):
          self.app.main_hero.nick = "Renamed"
          self.app.main_hero.num += 1
          self.app.val = self.app.main_hero  # not working need replace
          # probably something here (replacement)

class MainHero():
     def __init__(self):
          self.nick = "Player"
          self.num = 1
.
.
.
class Design(App):
     val = ObjectProperty()

     def __init__(self, **kwargs):
        super(Design, self).__init__(**kwargs)
        self.main_hero = MainHero() # Tried main_hero = MainHero() too
        self.val = self.main_hero  # object
.
.
.
Label:
     text: app.val.nick
     size_hint: .2, .2
     pos_hint: {'center_x': .5, 'center_y': .35}
Label:
     text: str(app.val.num)
     size_hint: .2, .2
     pos_hint: {'center_x': .7, 'center_y': .7}

Upvotes: 0

Views: 654

Answers (2)

John Anderson
John Anderson

Reputation: 39117

The StringProperty must be defined outside of a class method, like this:

class Design(App):
    val = StringProperty()  # defines the val property
    def __init__(self, **kwargs):
        super(Design, self).__init__(**kwargs)
        self.main_hero = MainHero()  # Tried main_hero = MainHero() too
        self.val = self.main_hero.nick  # set value of the property

Then, in your rename() method, you can just change the value of app.val

def rename(self):
    self.app.main_hero.nick = "Renamed"
    self.app.val = self.app.main_hero.nick

If you want to use the values in the MainHero class directly in kv, they must be Properties. But to make those attributes into Properties, the MainHero class must be a Widget or at least an EventDispatcher, like this:

class MainHero(EventDispatcher):
    nick = StringProperty()
    num = NumericProperty()

    def __init__(self):
        self.nick = "Player"
        self.num = 1

Upvotes: 1

vahidkoohkan
vahidkoohkan

Reputation: 192

You need to specify an ID for the label in the kv file and refer the action by which you want to change the text to a callback function, then change the text of the label in this way.

kv:

MDLabel:
        id: number
        text: "1"
        halign: "center"
        pos_hint: {"center_x": .5, "center_y": .5}

py:

class Screen2(Screen, n):
    def set_number(self):
        self.ids.number.text = f"{n}"

Upvotes: 0

Related Questions