11

i'm pretty new at using kivy library.

I have an app.py file and an app.kv file , my problem is that I can't call a function on button press.

app.py:

import kivy from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.uix.button import Button class Launch(BoxLayout): def __init__(self, **kwargs): super(Launch, self).__init__(**kwargs) def say_hello(self): print "hello" class App(App): def build(self): return Launch() if __name__ == '__main__': App().run() 

app.kv:

#:kivy 1.9.1 <Launch>: BoxLayout: Button: size:(80,80) size_hint:(None,None) text:"Click me" on_press: say_hello 

9 Answers 9

13

Mode:.kv

It's very simple, say_hello belongs to the Launch class so in order to use it in your .kv file you have to write root.say_hello. Note that say_hello is a function that you want to execute so you don't have to forget the () ---> root.say_hello().

Also, if say_hello were in App class you should use App.say_hello() because it belongs to the app. (Note: even if your App class were class MyFantasicApp(App): it would always be App.say_hello() or app.say_hello() I don't remember, sorry).

#:kivy 1.9.1 <Launch>: BoxLayout: Button: size:(80,80) size_hint:(None,None) text:"Click me" on_press: root.say_hello() 

Mode: .py

You can bind the function.

from kivy.uix.button import Button # You would need futhermore this class Launch(BoxLayout): def __init__(self, **kwargs): super(Launch, self).__init__(**kwargs) mybutton = Button( text = 'Click me', size = (80,80), size_hint = (None,None) ) mybutton.bind(on_press = self.say_hello) # Note: here say_hello doesn't have brackets. Launch.add_widget(mybutton) def say_hello(self): print "hello" 

Why use bind? Sorry, no idea. But you it's used in the kivy guide.

Sign up to request clarification or add additional context in comments.

1 Comment

You don't have to bind it if you make a separate MyButton class, where you would define a method on_press(). Probably too much work, unless you have other things to do with the Button.
3
from kivy.app import App from kivy.uix.button import Button from kivy.uix.label import Label class Test(App): def press(self,instance): print("Pressed") def build(self): butt=Button(text="Click") butt.bind(on_press=self.press) #dont use brackets while calling function return butt Test().run() 

1 Comment

very naughty variable names indeed!
2

say_hello is a method of the Launch class. In your kv rule, the Launch class is the root widget, so it can be accessed using the root keyword:

on_press: root.say_hello() 

Note also that you have to actually call the function, not just write its name - everything to the right of the colon is normal Python code.

Comments

2

I believe that the solution utilizing the bind function (given by Ender Look) will lead to the following error:

TypeError: pressed() takes 1 positional argument but 2 were given 

To solve this issue you have to allow the say_hello() module to accept the touch input as well, although it isn't needed.

2 Comments

Please clarify more your answer. If you use the parts of the code that you don't believe that work, it will be more helpful. Thanks
@EnriqueBet I tried the code above and kept getting the error I mentioned. I allowed say_hello() to accept another parameter to account for the Touch event and then everything worked fine. Is there another explanation? I'm new to Kivy and was just challenging myself to not use kv files, so that it would be easier to use whatever I learn here with other OOP languages.
1

For anyone is looking for a pure Python approach here is a general example.

To call a function without arguments:

def my_function(instance): ... my_button.bind(on_press=my_function) 

To call a function with arguments:

from functools import partial def my_function(instance, myarg): ... my_button.bind(on_press=partial(my_function,"a string")) 

Comments

1

If you would like to add function to any element in Kivy just use logic like here.

In your .py file:

class LoginButton(Button): def __init__(self, **kwargs): super().__init__(**kwargs) self.text = "Login" def login(self): print("logged_in") 

And then in .kv file:

LoginButton: id: "login" on_press: self.login() size_hint: None, None size: 500, 50 pos_hint: {"center_x": 0.5} 

It works for me :)

Comments

1

function with object as argument in kv-file

in kv:

on_press: root.say_hello(self) 

in py:

def say_hello(self,obj): print(obj) 

Comments

1
from kivy.app import App from kivy.uix.button import Button class MyApp(App): def build(self): return Button(text="Hello, Kivy!", on_press=self.on_button_click) def on_button_click(self, instance): instance.text = "Button Pressed!" if __name__ == '__main__': MyApp().run() 

Comments

0

you just added root before say_hello() function. like this

on_press: root.say_hello() 

it should working

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.