i've tried using '''App.get_running_app().close()''' but with no results at all, I have read the documentation but have not found anything useful, can you help me please?
Add on_press=lambda x: MDApp.stop(self) to your button if you are using python.
If you are using kv to do this then make a function,
def close_app(self):
MDApp.stop(self)
and add on_press: root.close_app() or on_press: app.close_app()to your kv button
Related
I have an application that at a certain point needs to check if a variable within its Python code has one value or another, and also requires a button capable of changing that variable from one value to another to also save that information in a text file and that the variable loads it the next time the application is started.
Here I prepared a small program to exemplify what I am looking for:
import kivy
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.lang.builder import Builder
from kivy.core.window import Window
Window.size=(200,200)
data=open('data.txt','r') #Let's say there is a text file called "data" that contains the number 0
Builder.load_string("""
<Screen>
BoxLayout:
orientation:'vertical'
size:root.width,root.height
Label:
text:'Switch On' if app.var==1 else 'Switch Off' #Initially then the label should say "Switch Off"
Button:
text:'Switcher'
on_release: #Change app.var from 0 to 1 or from 1 to 0
""")
class Screen(Widget):
pass
class App(App):
def build(self):
self.var=data.read()
#Save the changes made by the Button
return Screen()
if __name__=='__main__':
App().run()
How can I do this or something similar? A better and simpler way?
You should define a function and bind it to a button. The documentation can really help you here! you can bind your function using my_button.bind(on_press=on_button_click) where:
def on_button_click():
this.my_var += 1
Let me know if you think the documentation is unclear!
I'm using gestures in all of my screens, and I cannot use a screen manager class to manage my screens, or so I believe. I can navigate the .kv file by using manger.current = 'some_screeen' but cannot in the .py file.
I've been trying Runner().ids.manager.current = 'some_screen' in the .py file but it doesn't work. There isn't even an error thrown. The screen doesn't change at all.
Essential Code (for the sake of brevity):
class Runner(gesture.GestureBox):
pass
MyApp(App):
def build(self):
return Runner()
Then in the KV file, I'm creating the screen manager.
<Runner>:
ScreenManager:
id: manager
Screen:
name: 'main_screen'
Button:
on_press:
manager.current = 'screen1'
Screen:
name: 'screen1'
Button:
on_press:
manager.current = 'home_screen'
I've been trying Runner().ids.manager.current = 'some_screen' in the .py file but it doesn't work. There isn't even an error thrown. The screen doesn't change at all.
It works fine, it just doesn't do what you believe. When you write Runner() you get a new instance of the Runner class, with its own children including its own ScreenManager. This one has nothing to do with the one you're displaying in your gui. When you set its current property the ScreenManager will dutifully change the screen, it's just you have no way to see that.
What you actually want is to change the current property of the widget that you are displaying in your gui. The best way to do this depends on the context, which you have omitted (always try to provide a full runnable example, it isn't clear what your failing code looked like). However, in this case the Runner instance is your root widget which is accessible with App.get_running_app().root, so you can write App.get_running_app().root.ids.manager.current = 'some_screen'. Again, there might be neater ways to do it depending on how you structure your code, but this is always an option.
I have noticed that most examples I foind online don't have an external .kv file. They define all the instances internally. However they also say that having an external .kv file is a good practice. Which is better to do? If having external .kvfiles are better, then how am I supposed to use the code which uses internal code and turn it into external .kv files?
For example, doing this ->
from kivy.app import App
from kivy.uix.scatter import Scatter
from kivy.uix.label import Label
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.textinput import TextInput
from kivy.uix.boxlayout import BoxLayout
class TutorialApp(App):
def build(self):
b = BoxLayout(orientation='vertical')
t = TextInput(font_size=150,
size_hint_y=None,
height=200,
text='default')
f = FloatLayout()
s = Scatter()
l = Label(text='default',
font_size=150)
t.bind(text=l.setter('text'))
f.add_widget(s)
s.add_widget(l)
b.add_widget(t)
b.add_widget(f)
return b
if __name__ == "__main__":
TutorialApp().run()
Instead of-
<ScatterTextWidget>:
orientation: 'vertical'
TextInput:
id: my_textinput
font_size: 150
size_hint_y: None
height: 200
text: 'default'
FloatLayout:
Scatter:
Label:
text: my_textinput.text
font_size: 150
"Internal" usage of kv is through Builder class, which allows you even to load external file. Those examples are worded in a Builder.load_string(...) way because it's way simpler to have a small example in one place in one file.
How to convert it to the external one? Simple, copy&paste the string from Builder.load_string() into a separate .kv file with a name of your class that inherits from App(your main class with build()) and that's it. It'll load the same thing from the external file.
Why it's better or worse? Isn't any of that actually. It's like comparing "java" and python style i.e. either putting everything out of your file and having basically this construction a'la java, where the main file contains this:
class This(something):
SpecialClass.doThis()
AnotherClass.doThat()
and other classes(or different things) are in separate files. Or this construction:
class Special(...):
...
class Another(...):
...
class This(something):
Special.do_this()
Another.do_that()
Both of them are useful and you'll find yourself working with a mix between them. It's about transparency and clearness of your code, but maybe you don't want to have a hundred of files... or a 2MB main.py, pretty much compromise of how do you decide to code.
Edit:
The python vs kv is a funny "fight", but except a for(and while?) loop you can pretty much do everything necessary inside kv in such an easy way! Kv is here to make writing easier e.g. remove too much stuff like add_widget() or basically making an empty class just to rename a widget or to change its size for using it in one place.
With python in a 500line file without kv you won't do that much as with 100 extra lines in kv. The documentation has important parts in python and maybe it's even targeted for users who can't/don't want to use kv. Also this and all examples highly depend on the author of an example and that particular part of the docs.
Which returns me back to the java vs python style of coding I mentioned before. It's pointless to do complicated stuff just because you think it'll feel/look better if you can do it cleaner and more readable i.e. don't just go one way if you have a tool that increase your speed of coding exponentially. Find the middle way.
I have this code and it works, but I'm sure it's not the way to go properly. In my .kv a button fires two functions in my main.py.
Button:
text: "Press Me"
on_release: root.on_our_btn_release(text_input.text)
on_release: root.get_items(text_input.text)
Next step in my awesome project will be adding a lot more functions that will have to go off when the same button is clicked. This will result in a rather long list like:
Button:
text: "Press Me"
on_release: root.on_our_btn_release(text_input.text)
on_release: root.get_items(text_input.text)
on_release: root.another_function(text_input.text)
on_release: root.andanotherone(text_input.text)
on_release: root.herewegoagain(text_input.text)
on_release: root.this_is_getting_boring(text_input.text)
on_release: root.think_you_got_the_picture(text_input.text)
This looks to me as very ugly code, but I didn't find a pretty way to do this yet.
Anyone? Thanks in advance!
;-) Erik
You could structure this in a number of different ways, and the best option is mostly up to you.
One option if you don't want too many functions in kv is to call a single root.do_everything(), and put all the other calls in that on the python side.
I believe a slightly more elegant solution would be to indent and list the different callbacks.
on_release:
first()
second()
Another possible but ugly solution for this can be to separate the functions with a semicolon.
on_release: first(); second()
You could make use of "on_press" and "on_release". Assign one method/function to "on_press" and the other to "on_release"
I am trying to do some simple math in a kivy app using TextInput to allow users to input values. I defined the TextInput in the kv section of the code. I am unsure how to create a simple submit button to assign what's in the TextInput (which is defined in kv) to a variable so that I can do basic math with it in the python section.
You'll want to do something like the following:
BoxLayout:
orientation: 'vertical'
TextInput:
id: ti
Button:
text: 'do something!'
on_press: run_some_function_with_text(ti.text)
run_some_function_with_text would probably most usefully be a method of some other widget, but could be anything else you like, or you could just write the function inline if it's simple.