Search code examples
pythonkivytransitionkivy-language

Changing the kivy window transition direction pulls up an error when tried in different class?


So I'm doing a kivy practise app and I'm changing windows with WindowManager. We have an option to change the direction of the transition and it works perfectly somewhere but somewhere not and I don't completely understand why. I wanna fix this.

Here's my main program:

import kivy
from kivy.uix.widget import Widget
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.scrollview import ScrollView
from kivy.metrics import dp
from kivy.uix.stacklayout import StackLayout
from kivy.uix.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen

class MainWindow(Screen):
    pass
class SecondWindow(Screen):
    pass
class WindowManager(ScreenManager):
    pass


class ScrollScreen(ScrollView):
    pass

class StackLayoutExample(StackLayout):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        # for i in range(0, 400):
            #size = dp(100) + i*10
            #size = dp(100)
            #b = Button(text=str(i+1), size_hint=(None, None), size=(size, size))
            #self.add_widget(b)

class MyApp(App):
    pass

if __name__ == '__main__':
    MyApp().run()

Here's my .kv file:

WindowManager:
    MainWindow:
    SecondWindow:


<MainWindow>:
    name: 'main'
    ScrollScreen:
<SecondWindow>:
    name: 'second'
    Label:
        text: 'this is the second screen'
    Button:
        text: 'go back'
        on_release:
            root.manager.transition.direction = 'left'
            app.root.current = 'main'
            


<ScrollScreen@ScrollView>:
    do_scroll_x: False
    do_scroll_y: True

    StackLayoutExample:
        size_hint: 1, None
        height: 1000

<StackLayoutExample>:
    Button:
        text:'Press me!'
        size_hint: None, None
        pos_hint: {'center_x': .5, 'top': 1}
        width: "120dp"
        height: "60dp"
        on_release:
            root.manager.transition.direction = 'right'
            app.root.current = 'second'

And here's the traceback that I get when pressing the Press me -button in the Main window:

Traceback (most recent call last):
   File "c:\Users\aatut\Documents\Code\PythonProjektit\kivytraining\firstpractise\main.py", line 36, in <module>
     MyApp().run()
   File "C:\Users\aatut\Documents\Code\lib\site-packages\kivy\app.py", line 950, in run
     runTouchApp()
   File "C:\Users\aatut\Documents\Code\lib\site-packages\kivy\base.py", line 582, in runTouchApp
     EventLoop.mainloop()
   File "C:\Users\aatut\Documents\Code\lib\site-packages\kivy\base.py", line 347, in mainloop
     self.idle()
   File "C:\Users\aatut\Documents\Code\lib\site-packages\kivy\base.py", line 391, in idle
     self.dispatch_input()
   File "C:\Users\aatut\Documents\Code\lib\site-packages\kivy\base.py", line 342, in dispatch_input
     post_dispatch_input(*pop(0))
   File "C:\Users\aatut\Documents\Code\lib\site-packages\kivy\base.py", line 308, in post_dispatch_input
     wid.dispatch('on_touch_up', me)
   File "kivy\_event.pyx", line 709, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\aatut\Documents\Code\lib\site-packages\kivy\uix\behaviors\button.py", line 179, in on_touch_up
     self.dispatch('on_release')
   File "kivy\_event.pyx", line 705, in kivy._event.EventDispatcher.dispatch
   File "kivy\_event.pyx", line 1248, in kivy._event.EventObservers.dispatch
   File "kivy\_event.pyx", line 1132, in kivy._event.EventObservers._dispatch
   File "C:\Users\aatut\Documents\Code\lib\site-packages\kivy\lang\builder.py", line 57, in custom_callback
     exec(__kvlang__.co_value, idmap)
   File "c:\Users\aatut\Documents\Code\PythonProjektit\kivytraining\firstpractise\my.kv", line 37, in <module>
     root.manager.transition.direction = 'right'
   File "kivy\weakproxy.pyx", line 32, in kivy.weakproxy.WeakProxy.__getattr__
 AttributeError: 'StackLayoutExample' object has no attribute 'manager'

I would be glad if someone told me why this doesn't work and how to fix this/do the transitions like I would like to.


Solution

  • The error message is telling you that the StackLayoutExample has no manager attribute, because in your code:

    root.manager.transition.direction = 'right'
    

    root refers to the root of the rule in which it appears, which is the StackLayoutExample. You want to access the WindowManager, as you do in the line line where you set the current Screen. So your code should be:

        on_release:
            app.root.transition.direction = 'right'
            app.root.current = 'second'
    

    Note that when you reference app you are referencing the currently running App. And app.root refers to the root widget of the App. Just as any reference of the form object.attribute.

    However, when you start a reference with root, you are referencing the root object of the rule where that keyword is used. The the relevant documentation.