Lupos
Lupos

Reputation: 907

Kivy error while trying to change the screen

I didn't want to use the .kv language. So my problem occurs when trying to run a function when I press a button.
I found these question which had the same problem so I adopted the code, for the on_press method, from them:
kivy python passing parameters to fuction with button click
Python, Kivy, “AssertionError: None is not callable” Error on function call by button

The Error

File "kivy\_event.pyx", line 703, in kivy._event.EventDispatcher.dispatch
   File "kivy\_event.pyx", line 1214, in kivy._event.EventObservers.dispatch
   File "kivy\_event.pyx", line 1138, in kivy._event.EventObservers._dispatch
   File "C:\Users\schup\PycharmProjects\Workspace\kivy_app_go\Surface.py", line 28, in <lambda>
     btnHvH = Button(text="Human vs Human", size_hint=(0.35, 0.15), on_release=lambda *args: self.HelperMethodsInst.switch_screen(goal_screen="go_screen", Screenmanager=WindowManager.get_ScreenManager, *args))
 TypeError: switch_screen() got multiple values for argument 'Screenmanager'

Surface.py:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy_app_go.Control import HelperMethods
from kivy.properties import ObjectProperty
from kivy.graphics import Rectangle, Color, Line
from kivy.uix.label import Label
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.core.window import Window
from kivy.uix.screenmanager import FadeTransition

from functools import partial


class MenuScreen(Screen):
    def __init__(self, **kwargs):
        super(Screen, self).__init__(**kwargs)
        self.ScreenSize = Window.size
        self.HelperMethodsInst = HelperMethods()

        lytmain = FloatLayout(size=self.ScreenSize)
        lytbutton = BoxLayout(pos_hint={"y": 0.1, "x": 0.15}, size_hint=(2, 0.6), orientation='vertical', size=self.ScreenSize)

        lblHeadline = Label(text="Choose your Go Mode", font_size=40, pos_hint={"y": 0.8, "x": 0.325},
                            size_hint=(0.35, 0.15))
        btnHvH = Button(text="Human vs Human", size_hint=(0.35, 0.15), on_release=lambda *args: self.HelperMethodsInst.switch_screen(goal_screen="go_screen", Screenmanager=WindowManager.get_ScreenManager, *args))
        btnHvB = Button(text="Human vs Bot", size_hint=(0.35, 0.15), on_release=lambda *args: self.HelperMethodsInst.switch_screen(goal_screen="go_screen", Screenmanager=WindowManager.get_ScreenManager, *args))
        btnBvB = Button(text="Bot vs Bot", size_hint=(0.35, 0.15), on_release=lambda *args: self.HelperMethodsInst.switch_screen(goal_screen="go_screen", Screenmanager=WindowManager.get_ScreenManager, *args))

        self.add_widget(lytmain)
        lytmain.add_widget(lblHeadline)
        lytmain.add_widget(lytbutton)
        lytbutton.add_widget(btnHvH)
        lytbutton.add_widget(btnHvB)
        lytbutton.add_widget(btnBvB)



class GoScreen(Screen):
    def __init__(self, **kwargs):
        super(GoScreen, self).__init__(**kwargs)
        self.ScreenSize = Window.size

        lytmain = FloatLayout(size=self.ScreenSize)

        btnBack = Button(text="Back", size_hint=(0.25, 0.1))

        self.add_widget(lytmain)
        lytmain.add_widget(btnBack)


class WindowManager(ScreenManager):
    def __init__(self):
        self.sm = ScreenManager(transition=FadeTransition(duration=0.15))
        self.sm.add_widget(MenuScreen(name="menu_screen"))
        self.sm.add_widget(GoScreen(name="go_screen"))

    @property
    def get_ScreenManager(self):
        return self.sm

class Surface(App):
    def __init__(self):
        super().__init__()
        self.WindowManagerInst = WindowManager()

    def build(self):
        return self.WindowManagerInst.sm

    @staticmethod
    def create_Surface():
        return Surface().run()


def run():
    SurfaceInst = Surface()
    HelperMethodsInst = HelperMethods()



Control.py:

from kivy.uix.screenmanager import ScreenManager, Screen


class HelperMethods:
    def switch_screen(self, Screenmanager, goal_screen):
        screenmanager = goal_screen

main.py:

from kivy_app_go.Surface import Surface

if __name__ == "__main__":
    Surface.create_Surface()

I am new to kivy.
I hope someone can help ^^

Upvotes: 0

Views: 250

Answers (1)

John Anderson
John Anderson

Reputation: 39152

You are getting the

multiple values for argument 'Screenmanager'

error because your lambda is constructing a function with keyword arguments followed by *args. Since positional arguments must come before keyword arguments, your *args is treated as part of the Screenmanager= keyword. So that keyword is passed to your switch_screen method as

Screenmanager = WindowManager.get_ScreenManager, *args

If you need the Button instance (which is what the *args is) passed to your switch_screen method, then you need to modify that method to accept it (and adjust the lambda).

You can avoid the error simply by removing the *args from the end of the lambda.

However, there is another problem in that same line of code. You are using WindowManager.get_ScreenManager, but WindowManager is a class, not an instance, and in the class file get_ScreenManager is a property. So you need the WindowManager instance, which you can get from the WindowManagerInst attribute of the App. So that line now become: (along with a call to get the running App):

app = App.get_running_app()
btnHvH = Button(text="Human vs Human", size_hint=(0.35, 0.15), on_release=lambda *args: self.HelperMethodsInst.switch_screen(goal_screen="go_screen", Screenmanager=app.WindowManagerInst.get_ScreenManager))

Upvotes: 1

Related Questions