Вызов функции из другого класса в Kivy

#python #kivy

#python #kivy

Вопрос:

Итак, это мой код:

 from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen

x = 1

Builder.load_string("""

<One>:
    name: "one"
    GridLayout:
        cols:2
        Button:
            text: "Start"
            on_release:
                app.root.current = "two"
        Label:
            id: lbl
            text: "0"

<Two>:
    name: "two"
    Button:
        text: "Restart"
        on_release: 
            app.one.add()
            root.callotherfunction()
""")

class One(Screen):
    def add(self):
        global x
        x = x 1
        self.ids.lbl.text = str(x)
        sm.current = "one"
        print(str(x))

class Two(Screen):
    def callotherfunction(self):
        One().add()
        One().ids.lbl.text = "Two"

sm = ScreenManager()
sm.add_widget(One(name='one'))
sm.add_widget(Two(name='two'))

class MyMainApp(App):
    one = One()
    two = Two()
    def build(self):
        return sm

if __name__ == "__main__":
    MyMainApp().run()
  

То, что я пытаюсь сделать, это обновить метку на первом экране со второго экрана. Я попробовал два разных метода для вызова функции add, которые:

 app.one.add()
root.callotherfunction()
  

Оба они проходят и могут изменять экран и печатать обновленное значение x; однако им не удается обновить метку.

Я также пытался изменить метку из другого класса следующим образом:

 One().ids.lbl.text = "Two"
  

Опять же, метка не меняется. Если бы я мог заставить любой из этих методов работать, я был бы счастлив. Я новичок в Kivy и пытаюсь учиться, поэтому я ценю любую обратную связь. Спасибо.

Комментарии:

1. Вы не можете использовать One().<attribute> , потому что каждый раз, когда вы это делаете, вы создаете новый временный экземпляр, который мгновенно исчезает. Вам нужно добраться до оригинала one и two экземпляров. Я переработаю это и опубликую ответ.

Ответ №1:

Как я упоминал в своем комментарии, вы создаете новые экземпляры своих классов каждый раз, когда вызываете One() and Two() . Я не фанат глобальных переменных, но вот быстро переработанная версия вашего кода:

 from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen

x = 1

Builder.load_string("""

<One>:
    name: "one"
    GridLayout:
        cols:2
        Button:
            text: "Start"
            on_release:
                app.root.current = "two"
        Label:
            id: lbl
            text: "0"

<Two>:
    name: "two"
    Button:
        text: "Restart"
        on_release:
            root.callotherfunction()
""")

class One(Screen):
    def add(self):
        global x
        x = x 1
        self.ids.lbl.text = str(x)
        sm.current = "one"
        print(str(x))

class Two(Screen):
    def callotherfunction(self):
        one.add()
        #one.ids.lbl.text = "Two"

sm = ScreenManager()
one=One(name='one')
two=Two(name='two')
sm.add_widget(one)
sm.add_widget(two)

class MyMainApp(App):
    def build(self):
        return sm

if __name__ == "__main__":
    MyMainApp().run()
  

Комментарии:

1. Имеет больше смысла инициализировать x равным нулю, а не 1, потому что ваша начальная метка инициализируется значением «0».

2. Итак, когда вы устанавливаете one и two в качестве их соответствующих классов перед созданием виджета, это то, что делает так, что я не создаю временные экземпляры? И вы абсолютно правы в отношении начального значения x, это скорее доказательство концепции, чем приложение.

3. Когда я / вы создаете one=One(name='one') в основной программе, создается единственный экземпляр с именем one, который доступен для всех функций.