Search code examples
pythonpython-3.xkivytextinput

Kivy, Python3.5 - Bind user text input to method in class


Hy, this may be a stupid question, and it probably is, but is a stupid question that turned out to be very frustrating for me for the last couple of days so I just have to ask, can any of you guys help me with binding the mono-line text input to a method in a class? Here's my code, I'm a novice so any other criticism of it is welcome, it would help me improve, and thanks for taking the time in advance.

#//Random number generator//

import kivy
kivy.require('1.7.0')

from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.properties import ObjectProperty
from kivy.event import EventDispatcher
from kivy.properties import StringProperty
from kivy.uix.boxlayout import BoxLayout
import string
import random
from kivy.lang import Builder

Builder.load_string("""
<RootWidget>:
    BoxLayout:
        orientation: 'horizontal'
        canvas.before:
            Rectangle:
                pos: self.pos
                size: self.size
                source: "code.jpg"
        BoxLayout:
            orientation: "vertical"
            padding: 20
            spacing: 10

            AsyncImage:
                source: "img.png"
                size_hint: 1, 1
                pos_hint: {'center_x':.5, 'center_y': .5}

            Label:
                id: label_1
                text: root.data_model.c
                font_size: 17
                text_size: self.width, None
                color: [0,255,0]
                size_hint_y: .3
                pos_hint_y: {'center_x':.5, 'center_y': .5}

#-----------> Here <-------------

            TextInput:
                id: txt_inpt1
                text: "Lenght (optional)"
                size_hint_y: .2
                on_text: root.check_status(f_but)

# --------------> And Here <-----------------

            TextInput:
                id: txt_inpt2
                text: "Specific characters (optional)"
                size_hint_y: .2
                on_text: root.check_status(f_but)

            Button:
                id: btn_1
                text: "Generate"
                pos_hint_y: 
                on_press: root.button_press()
                size_hint_y: .3 
""")

class DataModel(EventDispatcher):
    b = StringProperty("")
    c = StringProperty("")

    def __init__(self, *args, **kwargs):
        super(DataModel, self).__init__(*args, **kwargs)
        self.bind(b=self.set_c)

    def set_c(self, instance, value):
        self.c = self.b


class RootWidget(BoxLayout):
    data_model = ObjectProperty(DataModel())

    def button_press(self, *args):

#---------> I want size to equal txt_inpt1 and chars txt_inpt2 <----------

        def id_generator(size=12, chars=string.ascii_uppercase + string.digits):
            return ''.join(random.choice(chars) for _ in range(size))

        text = id_generator()  
        self.data_model.b = text
        print (self.data_model.c)

class TestApp(App):

    def build(self):
        return RootWidget()

app = TestApp()
app.run()

Solution

  • You can access the those widgets using ids attribute (dictionary):

    def id_generator():
        try:
            size = int(self.ids['txt_inpt1'].text)
        except ValueError:
            size = 12
    
        chars = self.ids['txt_inpt2'].text or (string.ascii_uppercase + string.digits)
        return ''.join(random.choice(chars) for _ in range(size))