Search code examples
pythonkivynameerror

NameError: name "winroot" is not defined


I am building a calculator app, and I solved a lot of problems except this one. It is bigger than me to solve it, I tried nearly everything except 1 way that I am thinking of it right now is: making the program in one (.py) file.

My program is designed in Kivy and I made the app in two python files, so here is the problem: the main screen has several choices to open a new page, and that page must have a button that make the app gets back to the main screen, and this button did not work.

A variable has just disappeared magically .. called 'winroot'!

Here is the code (main.py):

class Base(App):
    def build(self):
        global winroot
        winroot = TheMainScreen()
        mnsc = MainScreen()
        winroot.add_widget(mnsc)
        return winroot
class TheMainScreen(FloatLayout):
    def back(self, obj=1):
        print('pressed')
        winroot.clear_widgets()
        winroot.add_widget(MainScreen())
class MainScreen(FloatLayout):
    def __init__(self, **kwargs):
        self.B1 = Button(text='Base Calculator\n\n\n', on_press=self.basecalc)
    def basecalc(self, obj):
        winroot.clear_widgets()
        from calculator.basecalculator import BaseCalculator
        winroot.add_widget(BaseCalculator())

and this is for the second python file (basecalculator.py):

class BaseCalculator(FloatLayout):
    def __init__(self, **kwargs):
        super(BaseCalculator, self).__init__(**kwargs)
        self.B11 = Button(size_hint=(.08, .13), on_release=self.prev)
    def prev(self, obj=1):
        from calculator.main import TheMainScreen
        a = TheMainScreen()
        a.back()

and here is the Error that is showing up :

File "C:\Users\work\PycharmProjects\Kivy\calculator\basecalculator.py", line 95, in prev
 a.back()

File "C:\Users\work\PycharmProjects\Kivy\calculator\main.py", line 26, in back winroot.clear_widgets()
NameError: name 'winroot' is not defined

Solution

  • since winroot is a global variable created inside a function, you have to declare it as global in every function you use it.

    Or, you know, instead of global, set is as instance attribute and pass it around, then you don't need globals:

    class Base(App):
        def build(self):
            self.winroot = TheMainScreen()
            self.mnsc = MainScreen(self.winroot)
            self.winroot.add_widget(self.mnsc)
            return winroot
    
    
    class TheMainScreen(FloatLayout):
        def back(self, obj=1):
            print('pressed')
            self.clear_widgets()
            self.add_widget(MainScreen())
    
    
    class MainScreen(FloatLayout):
        def __init__(self, winroot, **kwargs):
            self.B1 = Button(text='Base Calculator\n\n\n', on_press=self.basecalc)
            self.winroot = winroot
    
        def basecalc(self, obj):
            self.winroot.clear_widgets()
            from calculator.basecalculator import BaseCalculator
            self.winroot.add_widget(BaseCalculator())