Reputation: 31
I have a simple example of the issue below. I have three classes MyLayout (root), Pop a popup class and MyBox which is a Boxlayout created dynamically with a click of a button in MyLayout. I have made the capitalise() function in root that works with the popup fields. My issue is interaction with instances of MyBox. for example how can the popup know which MyBox called it and return the first name + last Name to the appropriate TextInput box?
Also if I wanted to collate all the data in the TextInput boxes across all the MyBox instances, how would i do that. I assume using properties.
Thanks in advance
# filename popper.py
from kivy.app import App
from kivy.uix.popup import Popup
from kivy.uix.stacklayout import StackLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
Builder.load_string('''
#:import Factory kivy.factory.Factory
<MyBox>:
orientation:'vertical'
TextInput:
text: 'N/A'
Button:
text: 'Choose a name'
on_press: Factory.Pop().open()
<Pop>:
auto_dismiss: False
title: 'Names'
size_hint: [0.4, 0.5]
pos_hint:{'right': 0.4, 'top': 1}
id: msg_box
GridLayout:
id: _pop
rows: 3
GridLayout:
id: pop_grid
cols:2
padding: [0,5]
Spinner:
text: 'First Name'
id: fn
sync_height: True
values: ['andrew', 'brian', 'colin', 'david', 'edmond']
width: self.width
on_text: self.text = app.root.capitalise(self.text)
Spinner:
text: 'Last Name'
id: ln
sync_height: True
values: ['Adams', 'Bass', 'Carney', 'Davies', 'Edmonds']
width: self.width
Button:
padding: [0,5]
text: 'OK'
on_release: root.dismiss()
width: self.width
<MyLayout>:
orientation: 'tb-lr'
size_hint: .2, 0.5
width: self.width
Button:
text: 'Create name box.'
on_press: app.root.make_name_box()
width: 300
''')
class MyLayout(StackLayout):
pass
def make_name_box(self):
self.add_widget(MyBox())
def capitalise(self, text):
return text.capitalize()
class Pop(Popup):
def __init__(self, **kwargs):
super(Pop, self).__init__(**kwargs)
class MyBox(BoxLayout):
def __init__(self, **kwargs):
super(MyBox, self).__init__(**kwargs)
size_hint = None, None
width = 300
class PopperApp(App):
def build(self):
return MyLayout()
if __name__ =='__main__':
PopperApp().run()
Upvotes: 2
Views: 236
Reputation: 2231
The main thing you want is to pass a reference of the "creator" box to the "created" popup. You can do that by passing the widget at creation time on_press: Factory.Pop(root).open()
Full working code here:
Builder.load_string('''
#:import Factory kivy.factory.Factory
<MyBox>:
orientation:'vertical'
TextInput:
text: root.box_text # bind the text to the box_text
Button:
text: 'Choose a name'
on_press: Factory.Pop(root).open() # pass the creator of the pop here
<Pop>:
auto_dismiss: False
title: 'Names'
size_hint: [0.4, 0.5]
pos_hint:{'right': 0.4, 'top': 1}
id: msg_box
GridLayout:
id: _pop
rows: 3
GridLayout:
id: pop_grid
cols:2
padding: [0,5]
Spinner:
text: 'First Name'
id: fn
sync_height: True
values: ['andrew', 'brian', 'colin', 'david', 'edmond']
width: self.width
on_text: self.text = app.root.capitalise(self.text)
Spinner:
text: 'Last Name'
id: ln
sync_height: True
values: ['Adams', 'Bass', 'Carney', 'Davies', 'Edmonds']
width: self.width
Button:
padding: [0,5]
text: 'OK'
on_release:
root.creator.box_text = "{} {}".format(fn.text, ln.text) # use the creator reference
root.dismiss()
width: self.width
<MyLayout>:
orientation: 'tb-lr'
size_hint: .2, 0.5
width: self.width
Button:
text: 'Create name box.'
on_press: app.root.make_name_box()
width: 300
''')
class MyLayout(StackLayout):
pass
def make_name_box(self):
self.add_widget(MyBox())
def capitalise(self, text):
return text.capitalize()
class Pop(Popup):
def __init__(self, creator, **kwargs):
super(Pop, self).__init__(**kwargs)
self.creator = creator # keep a reference to the creator here
class MyBox(BoxLayout):
box_text = StringProperty("N/A")
def __init__(self, **kwargs):
super(MyBox, self).__init__(**kwargs)
size_hint = None, None
width = 300
class PopperApp(App):
def build(self):
self.my_layout = MyLayout()
return self.my_layout
def on_stop(self): # print the names when leaving the app
boxes = self.my_layout.children[:-1]
print([i.box_text for i in boxes])
if __name__ == '__main__':
PopperApp().run()
EDIT: As for the second question, I added the printing of the names as you close the app.
Upvotes: 1