Reputation: 51
I am using kvlang to define the UI layout for my kivy test app. I use a Button as the root widget and I want a Popup to appear when the button is pressed.
To do this I specify "on_press: app.do_popup()" property in the .kv file.
Can I define the popup that will appear as a named class in the same .kv file and reference it from the do_popup() definition, or do I have to define it in the application's main.py file?
Thanks and Regards!
EDIT:
here is the case where the widget is defined in the .py file:
.py:
from kivy.app import App
from kivy.uix.popup import Popup
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
class kkkApp(App):
def do_popup(self):
pu = Popup(title = 'title', size_hint = (0.5, 0.5))
box = BoxLayout(orientation = 'vertical')
lab = Label(text = 'text', size_hint = (1, 5))
but = Button(text = 'Close', size_hint = (1, 1))
box.add_widget(lab)
box.add_widget(but)
pu.add_widget(box)
pu.open()
but.bind(on_release = pu.dismiss)
kkkApp().run()
.kv:
<MaButton@Button>:
text: '123'
<MaPopup@Popup>:
auto_dismiss: True
# ... more stuff defining the popup with button and behavior...
MaButton:
id: main_button
on_release: app.do_popup()
the question is whether there is some way to leverage kvlang and write less python using the MaPopup defined in the kv-file as follows:
.py:
from kivy.app import App
class kkkApp(App):
def do_popup(self):
pu = MaPopup(title = 'title', size_hint = (0.5, 0.5))
pu.open()
kkkApp().run()
where the omitted stuff is defined in the .kv file
Upvotes: 3
Views: 2546
Reputation: 2414
Yes, you can defined any object/layout in the .kv file and reference it in the main .py file and I believe that's the way to go in Kivy. However, instead of deriving from the Popup class (as in <MaPopup@Popup>
), I would suggest defining the content of the popup and provide it when creating a Popup instance in the main .py file. There is no need to subclass Popup when all you are interested in are its contents.
So, to create the popup content in .kv based on what you declared in your .py file:
<MaPopup@BoxLayout>:
orientation: "vertical"
Label:
text: "text"
size_hint: (1,5)
Button:
text: "Close"
size_hint: (1,1)
on_release: root.cancel()
Since MaPopup
is a BoxLayout and not a Popup, it does not have a dismiss
method, so we'll bind root.cancel()
to on_release
and give it functionality in the .py file.
In you .py file, you'll need to create a Class with the same name AND define the cancel
attribute that was referenced in the .kv file (which will be None for starters):
from kivy.properties import ObjectProperty
class MaPopup(BoxLayout):
cancel = ObjectProperty(None)
This will allow you to create any instances you want of MaPopup
and insert it wherever you want in your .py file.
Finally, you can create a Popup using an instance MaPopup
as its contents. There are a few extra lines that will help you make the opening/closing of Popups of more general use
class kkkApp(App):
# Use this class attribute to reference Popups
_popup = None
# Use this method to close Popups referenced by _popup
def _dismiss_popup(self):
self._popup.dismiss()
def do_popup(self):
# Instantiate MaPopup and give functionality to cancel button
popup_content = MaPopup(cancel=self._dismiss_popup)
self._popup = Popup(title = 'title', size_hint = (0.5, 0.5), content=popup_content)
self._popup.open()
Notice that we created an instance of MaPopup
named popup_content
and provided this instance as the Popup content using the content=
keyword. We also added functionality to the cancel button at this stage, which gives you flexibility to bind the on_release
event to any other method you want. You could create another MaPopup
a give an entirely different function to the cancel button.
Upvotes: 4