Search code examples
pythonkivypython-3.9

In Kivy I can't call a function from widget class from any class


The problem is that any class doesn't execute a function in the widget class, it doesn't give any error when the key is pressed but the command doesn't work.

py.


import kivy

from kivy.app import App

from kivy.uix.widget import Widget

from kivy.uix.boxlayout import BoxLayout

from kivy.uix.button import Button

from kivy.uix.label import Label

from kivy.lang import Builder

from kivy.clock import Clock

from functools import partial

from kivy.uix.popup import Popup

Builder.load_file("wideneme.kv")

class Tryer(Popup):

    

    def prot(self):

        MyLayout().play_activator()

class MyLayout(Widget):

    def __init__(self, **kwargs):

        super(MyLayout, self).__init__(**kwargs)

        

        self.empty = False

    

    def op(self):

        den = Tryer()

        den.open()

        

    def play_activator(self):

        self.ids.bt.text = "Changes"

        

class FirstApp(App):

    def __init__(self, **kwargs):

        super().__init__(**kwargs)

        

        self.ml = MyLayout()

        

    def build(self, **kwargs):

        return self.ml

        

if __name__ == "__main__":

    FirstApp().run()

kv.


<MyLayout>:

    BoxLayout:

        orientation: "vertical"

        Button:

            id: bt

            text: "ML"

            size_hint_x: 2

            size_hint_y: 2

            on_release: root.op()

            

<Tryer>:

    size_hint_x: .5

    size_hint_y: .5

    Button:

        id: btn

        text: "Den"

        size_hint_x: 1

        size_hint_y: 1

        on_release: root.prot()

I also tried assigning a normal variable, but it gave the same result. I can't run it from inside the kv file because I need to run it from the python file in the original code, so don't suggest commands like app.root from inside the kv file, the original code has the same codes as here, but it doesn't have any keys to run the function in the Widget class and I can't put it. It doesn't work in solutions like Objectproperty and id.


Solution

  • The problem in your code is the line:

    MyLayout().play_activator()
    

    The issue is that the line of code is creating a new instance of MyLayout and calling its play_activator() method. However, that new instance of MyLayout is not part of your GUI, so no effect is visible. The fix is to make sure that you reference the instance of MyLayout that is actually in your GUI. There are two simple ways to do this:

    1. Modify the code in the prot() method like this:

      def prot(self):
          # MyLayout().play_activator()
          App.get_running_app().root.play_activator()
      
    2. Modify your kv code like this:

      on_release: app.root.play_activator()
      

    Either of the above choices should work.