Search code examples
pythonkivykivy-language

How to tie kv and py?


I am new at Kivy and Python and I have difficulties with tying kv code and py code. Here I go from a splash screen to login menu. I ask for name and age of the child using TextInput in kv and try to print it in py code, but I get this mistake:

PrintData() takes 2 positional arguments but 3 were given

I think I made some kind of stupid mistake or chose a wrong way to organise code.

My code:

from kivy.app import App


from kivy.lang import Builder

from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import StringProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput

Builder.load_string('''
<RootScreen>:
    transition: FadeTransition()
    IntroScreen:
    NameScreen:

<IntroScreen>:
    AnchorLayout:
        Image:
            source: 'yCFD2.png'
            size_hint: 1,1
        Button:
            background_color: [63, 191, 63, 0.0]
            text: ''
            on_press: root.manager.current = 'data'

<NameScreen>:
    canvas.before:
        Rectangle:
            pos: self.pos
            size: self.size
            source: 'X6TF0.png'
    FloatLayout:
        TextInput:
            id: ChildName
            size_hint:.2, .2
            pos_hint:{'x': 0.7, 'y': 0.4}
            text: "Введи имя"
            focus: True
            multiline: False
        TextInput:
            id: ChildAge
            size_hint:.2, .2
            pos_hint:{'x': 0.7, 'y': 0.6}
            text: "Введи возраст"
            focus: True
            multiline: False
        Button:
            size_hint:.2, .2
            pos_hint:{'x': 0.7, 'y': 0.8}
            background_color: [63, 191, 63, 0.3]
            text: 'Добавить в базу'
            on_press: root.PrintData(ChildName, ChildAge)
''')


class IntroScreen(Screen):
    def intro(self):
        pass

class NameScreen(Screen):
    ChildName = StringProperty()
    ChildAge = StringProperty()

    def __init__(self, **kwargs):
        super(NameScreen, self).__init__(**kwargs)
        self.ChildName = ''

    def __init__(self, **kwargs):
        super(NameScreen, self).__init__(**kwargs)
        self.ChildAge = ''

    def PrintData(ChildName, ChildAge):
        print(ChildName, ChildAge)


sm = ScreenManager()
sm.add_widget(IntroScreen(name='intro'))
sm.add_widget(NameScreen(name='data'))

class SampleApp(App):
    def build(self):
        return (sm)

if __name__ == "__main__":
    SampleApp().run()

Solution

  • Explanation

    The first parameter that are passed to the on_<property_name> event or the function bound to the property is self, which is the instance of the class where this function is defined.

    Solution

    Please refer to the following snippets and example for the solution.

    Snippets

    Python Script

    def PrintData(self, ChildName, ChildAge):
        print(ChildName, ChildAge)
    

    kv file

    on_press: root.PrintData(ChildName.text, ChildAge.text)
    

    Example

    main.py

    from kivy.app import App
    from kivy.uix.screenmanager import ScreenManager, Screen
    from kivy.properties import StringProperty
    
    
    class IntroScreen(Screen):
        def intro(self):
            pass
    
    
    class NameScreen(Screen):
        ChildName = StringProperty()
        ChildAge = StringProperty()
    
        def __init__(self, **kwargs):
            super(NameScreen, self).__init__(**kwargs)
            self.ChildName = ''
    
        def __init__(self, **kwargs):
            super(NameScreen, self).__init__(**kwargs)
            self.ChildAge = ''
    
        def PrintData(self, ChildName, ChildAge):
            print(ChildName, ChildAge)
    
    
    class RootScreen(ScreenManager):
        pass
    
    
    class SampleApp(App):
        def build(self):
            return RootScreen()
    
    
    if __name__ == "__main__":
        SampleApp().run()
    

    sample.kv

    #:kivy 1.10.0
    #:import FadeTransition kivy.uix.screenmanager.FadeTransition
    
    <RootScreen>:
        transition: FadeTransition()
        IntroScreen:
            name: 'intro'
        NameScreen:
            name: 'data'
    
    <IntroScreen>:
        AnchorLayout:
            Image:
                source: 'kivyLogo.png' # 'yCFD2.png'
                size_hint: 1,1
            Button:
                background_color: [63, 191, 63, 0.0]
                text: ''
                on_press: root.manager.current = 'data'
    
    <NameScreen>:
        canvas.before:
            Rectangle:
                pos: self.pos
                size: self.size
                source: 'kivymd_logo.png'  # 'X6TF0.png'
        FloatLayout:
            TextInput:
                id: ChildName
                size_hint:.2, .2
                pos_hint:{'x': 0.7, 'y': 0.4}
                text: "Введи имя"
                focus: True
                multiline: False
            TextInput:
                id: ChildAge
                size_hint:.2, .2
                pos_hint:{'x': 0.7, 'y': 0.6}
                text: "Введи возраст"
                focus: True
                multiline: False
            Button:
                size_hint:.2, .2
                pos_hint:{'x': 0.7, 'y': 0.8}
                background_color: [63, 191, 63, 0.3]
                text: 'Добавить в базу'
                on_press: root.PrintData(ChildName.text, ChildAge.text)
    

    Output

    Img01 - App Startup Img02 - Child Name & Age Img03 - Print Child Name & Age