0

I would like to start with Kivy since I code in Python but I find it really hard! Can you lead to a good explanation of how it works? For example even this looks quite foggy (that is the second example of their website).

from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput


class LoginScreen(GridLayout):

    def __init__(self, **kwargs):
        super(LoginScreen, self).__init__(**kwargs)
        self.cols = 2
        self.add_widget(Label(text='User Name'))
        self.username = TextInput(multiline=False)
        self.add_widget(self.username)
        self.add_widget(Label(text='password'))
        self.password = TextInput(password=True, multiline=False)
        self.add_widget(self.password)


class MyApp(App):

    def build(self):
        return LoginScreen()


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

I would like to start with a basic App that asks user for input and display something created from it. For example in basic Python without any GUI it could be:

def hex_enc(text_input):
    return text_input.encode('hex')

def hex_dec(text_input):
    return text_input.decode('hex')

while True:
    text_input = raw_input('Input  : ')
    mode = raw_input('Mode   : ').lower()
    if ('encrypt' in mode):
        print hex_enc(text_input)
    else:
        print hex_dec(text_input)

I think I would need one textinput and one label which would be the result of that textinput. But this is very messy and I don't know and to use all of that into kivy class!

rkyr
  • 3,131
  • 2
  • 23
  • 38
John Doe
  • 1
  • 1
  • 1

1 Answers1

4

Okay. Here's an example implemented solely in Python, without a .kv file. I've got some comments in there to try to explain what's going on step-by-step. It'll pop up a text box that the user can type stuff into, and spit that back out in a label, after adding an exclamation mark. You can obviously do more interesting stuff than adding punctuation, but I decided to keep the example simple.

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput


class MyDumbScreen(BoxLayout):  # Changed to a BoxLayout for simplicity

    def __init__(self, **kwargs):
        # Call the base class constructor :)
        # Note that this is where it will pick up on any stuff you did in the
        # .kv file (if you have one)
        super(MyDumbScreen, self).__init__(**kwargs)
        self.orientation = "vertical"

        # Here we are just creating a text input
        my_user_input = TextInput()

        # Here we add it to MyDumbScreen's widget tree.  If you skip this step,
        # you'll never see your precious widget.
        self.add_widget(my_user_input)

        # This is the label that will hold a modified version of the user's
        # input
        my_output = Label(text="initial value")
        self.add_widget(my_output)

        # Here we create a callback function
        # This callback will be called whenever the 'text' property of
        # our TextInput is modified
        def callback(instance, value):
            my_output.text = value + "!"

        # Here we "bind" the callback to the TextInput's 'text' property
        # If you skip this step, you won't see the changes ever take place
        my_user_input.bind(text=callback)


class MyApp(App):

    def build(self):
        return MyDumbScreen()


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

Note that I typically regard this as being a more complicated approach than simply using a .kv file.

If you went that route, your class definition would look like this:

class MyDumbScreen(BoxLayout):  # Changed to a BoxLayout for simplicity
    pass

And your .kv file would look like this:

<MyDumbScreen@BoxLayout>:
    orientation: "vertical"

    TextInput:
        id: my_user_input
        text: ""
    Label:
        id: my_output # This id isn't serving a purpose
        text: my_user_input.text + "!"

With the .kv approach, you didn't have all the noise of adding stuff to the widget tree manually, or writing/adding a callback yourself.

Remember that, by default, Kivy will load the kv file based on the name of your App class and the name of the .kv file, and that case sensitivity varies by os.

Will
  • 928
  • 11
  • 10
  • I went with your MyApp.kv alternative suggestion and only get a black screen. Do you have your example code somewhere? – Dale E. Moore Sep 08 '17 at 15:09
  • You mean the example code posted in the answer above? Yes. I copied/pasted to verify. It works, at least on my system, which I believe is on the latest version. I did not, however, but any file names in my answer. If you're getting a black screen with no error message, I'm guesing Kivy failed to find your *.kv file. If you're on a *nix system, make sure you're not running into case sensitivity issues. Otherwise, make sure you don't, for instance, have "app" in the name of your kv file. If your py file is named "myapp.py", kivy will look for "my.kv". – Will Sep 10 '17 at 17:37
  • Thanks Will! Changed MyApp(App) to myapp and all references; and, my.kv. Working perfectly now! – Dale E. Moore Sep 10 '17 at 19:29
  • Kivy should convert the class name to lower case when searching for the kv file anyway; case issues should only be a problem if you use uppercase in your file names. I'm guessing you'd named your kv file something like myapp.kv, and that was the problem. – Will Sep 11 '17 at 22:49