Reputation: 89
The end goal is to create entries in a database with info from a form, using a variety of widgets (textinput, checkboxes,etc). I wanted to make a button at the end of the form to submit the responses to a dict, but I am getting stuck. The only way I can think of to accomplish this is to make all the ids to object properties, then individually reference them in a function like series1.value... series2.value...
This seems very cumbersome and would make it difficult to add further entries to the form later on.
Here is my .py:
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
from kivy.uix.checkbox import CheckBox
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.button import Button
class DermRoot(BoxLayout):
dict_filled_from_form = {}
def add_entry_to_db(self,dict_filled_from_form):
pass
class DemographForm(BoxLayout):
sex = ObjectProperty()
age_input = ObjectProperty()
def add_entry(self,dict_of_form):
dict_filled_from_form = dict_of_form
#is this possible?
#or do I have to do dict_filled_from_form['series1'] = series1.value etc
class DermApp(App):
pass
if __name__ == '__main__':
DermApp().run()
and my kv file
DermRoot:
<DermRoot>:
DemographForm
<DemographForm>:
orientation: "vertical"
GridLayout:
age_input: age_input
sex: sex
cols: 2
Label:
text: "Patient's Age:"
TextInput:
id: age_input
focus: series4
multiline: False
Label:
text: "Sex:"
ToggleButton:
id: sex
text: "Male" if self.state == 'normal' else "Female"
Label:
text: "Standard Series to Include?"
GridLayout:
series1: series1
series2: series2
series3: series3
series4: series4
series5: series5
cols: 2
CheckBox:
id: series1
Label:
text: "Series1"
CheckBox:
id: series2
Label:
text: "Series2"
CheckBox:
id: series3
Label:
text: "series"
CheckBox:
id: series4
Label:
text: "series4"
CheckBox:
id: series5
Label:
text: "Series 5"
Button:
height: "40dp"
size_hint_y: None
text: "Add Entry to Database"
on_press: root.add_entry(dict_of_form = 'how do I get this?')
Upvotes: 5
Views: 4359
Reputation: 14824
The best option is to use a DictProperty
. Try adding one to DemographForm
:
class DemographForm(BoxLayout):
data = DictProperty({})
In your kv, you can use it like so:
Label:
text: "Patient's Age:"
TextInput:
multiline: False
# set the value from the data dict. if the key
# doesn't exist in the dict, then use a default value
text: root.data['age'] if 'age' in root.data else ''
# when the value changes, update the data dict
on_text: root.data['age'] = self.text
This also makes it much easier to handle editing records later. If you set a new dict to data
, it will populate all of the fields in the form. Let's add an edit()
method to DemographForm
:
def edit(self, data=None):
if data is not None:
self.data = data
else:
self.data = {} # reset the form
So you can populate or reset the form. How do you get the data back out? There are different ways to do this, but let's use an event. In DemographForm
, add an __events__
attribute and a default handler:
__events__ = ('on_save', )
def on_save(self, data):
pass
The default handler doesn't have to do anything. You're just required to define it if you create an event. Next we can hook it up to the save button in kv:
Button:
height: "40dp"
size_hint_y: None
text: "Add Entry to Database"
# dispatch our new `on_save` event
on_press: root.dispatch('on_save', root.data)
Now that you have an on_save
event, you can bind to that in your kv in the same way:
<DermRoot>:
DemographForm:
# the arguments to the handler are available
# as `args` - the last argument will be our
# data, so we can grab it via `args[-1]`
on_save: root.add_entry_to_db(args[-1])
Upvotes: 7