Search code examples
pythonkivypython-3.9

Kivy function not producing results when called from other classes


The code works without any error but it doesn't give any results. My question is how can I call a function in mainmenu class from firstscreen or any class because i still cant call another class and i cant write (return MainMenu) from FirstApp class.

Is it possible to change between 2 widget classes while the code is running? (return FirstScreen) - (return MainMenu) this is not the main question so you don't have to answer

import kivy
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.image import Image
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.image import Image
from kivy.core.window import Window
from kivy.properties import NumericProperty
from kivy.properties import ObjectProperty
#from kivy.storage.jsonstore import JsonStore
from kivy.animation import Animation
from kivy.clock import Clock
from kivy.clock import mainthread
from functools import partial
from kivy.lang import Builder
import sys
import os
import android
import json

class MainMenu(Widget):
    def __init__(self, **kwargs):
        super(MainMenu, self).__init__(**kwargs)
        
    @mainthread
    def scOpener(self, *args):
        self.ids.mmb.pos = (-200, 0)

class FirstScreen(Widget):
    def __init__(self, **kwargs):
        super(FirstScreen, self).__init__(**kwargs)
        
        self.mm = MainMenu()
        
        self.gsa()
        
    def den(self, *args):
        self.mm.scOpener()
        
    def gsa(self, *args):
        animate = Animation(
        duration = 1.3,
        opacity = .9)
        animate.start(self)
        animate.bind(on_complete = self.den)
        
class FirstApp(App):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        
        self.sv = SaveWin()
        self.fs = FirstScreen()
        self.mm = MainMenu()
        
    def build(self, **kwargs):
        Window.clearcolor = (0,0,0,1)
        return self.fs
        
if __name__ == "__main__":
    try:
        os.remove("./fs.json")
        os.remove("./fs_data.json")
        os.remove("./k1Data.json")
        os.remove("./k2Data.json")
        os.remove("./k3Data.json")
    except:
        pass
    FirstApp().run()
<FirstScreen>
    background_color: 0,0,0,0
    opacity: 1
    
    MainMenu:
        size: root.width, root.height
        
<MainMenu> 
    opacity: 1
    FloatLayout:
        size: root.width, root.height
        opacity: 1
        #padding: 0
        #spacing: 0
        
        Image:
            id: mmb
            source: "images/main menu background.jpg"
            size_hint: 1.17, 1.17
            pos: -20000, 0
            allow_stretch: True
            keep_ratio: True

When I run the code separately from the mainmenu (scOpener) it works fine, but I can't run it from other classes. When i try, nothing happens, no error, no changes. If its important, i try the objectproperty method but it gives me (Invalid data after declaration) error for .kv file.


Solution

  • Whenever you execute code like:

    self.mm = MainMenu()
    

    you are creating a new instance of MainMenu that is unrelated to any other instance of MainMenu. There are two places in your code where you have such a line. There is also a line in your kv:

    MainMenu:
    

    which creates another instance of MainMenu. None of these instances are related. Calling methods of one will not affect the others.

    In order to access the instance of MainMenu that you need, you can add an id to your kv file:

    <FirstScreen>
        background_color: 0,0,0,0
        opacity: 1
        
        MainMenu:
            id: mm
            size: root.width, root.height
    

    Then use that id to access the correct instance of MainMenu:

    class FirstScreen(Widget):
        def __init__(self, **kwargs):
            super(FirstScreen, self).__init__(**kwargs)
    
            self.mm = self.ids.mm
    
            self.gsa()