so right now I am trying to create a list in a kivy app. The app grabs data from a text file. The text file receives new data after the submission of information from the user, I would like the list to update every time the user submits more data. In this case the data is the names of colleges. I have been digging and digging for an answer to this problem but just cant seem to figure it out, I keep getting errors. Also, I am pretty new to programming in python (and programming in general) and this is also my first kivy app so excuse my lack of knowledge and stupidity. Below I have posted my python and kivy files along with the text file (just in case). Please help!
.py
from kivy.properties import ObjectProperty, ListProperty
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from database import DataBase
from kivy.app import App
from kivy.uix.recycleview import RecycleViewBehavior
class MainPage(Screen):
pass
class NewEntryPage(Screen, RecycleViewBehavior):
addschool = ObjectProperty(None)
costofsecondary = ObjectProperty(None)
addtravelexpenses = ObjectProperty(None)
ListOfSchools = ListProperty([])
def pressBtn(self):
newSchool = self.addschool.text
costOfSecondary = self.costofsecondary.text
addTravelExpense = self.addtravelexpenses.text
print("New School:", newSchool, "\nCost Of Secondary:", costOfSecondary, "\naddTravelExpense:", addTravelExpense, "\n", self.ListOfSchools)
if self.addschool.text != "" and self.costofsecondary.text != "" and self.addtravelexpenses.text != "":
db.add_school_and_secondary(self.addschool.text, self.costofsecondary.text, self.addtravelexpenses.text)
self.reset()
SchoolsAppliedToPage().updatelist("/Users/PycharmProjects/msft/schools.txt", self.ListOfSchools)
def reset(self):
self.addschool.text = ""
self.costofsecondary.text = ""
self.addtravelexpenses.text = ""
class SchoolsAppliedToPage(Screen):
rvlist = ObjectProperty(None)
ListOfSchools = NewEntryPage.ListOfSchools
def updatelist(self, filename, listofschools):
file = open(filename, "r")
for line in file:
school, cos, ate, space = line.strip().split(";")
listofschools.append(school)
self.rvlist.data.append([{'text': school} for school in listofschools])
print(listofschools)
print(self.ListOfSchools)
class WindowManager(ScreenManager):
pass
kv = Builder.load_file("msft.kv")
db = DataBase("/Users/PycharmProjects/msft/schools.txt")
class msftApp(App):
def build(self):
return kv
if __name__ == '__main__':
msftApp().run()
.kv
ScreenManager:
MainPage:
NewEntryPage:
SchoolsAppliedToPage:
<Button>
font_size:40
font_name: "/Users/Desktop/App_Files/Antonio-Bold.ttf"
size_hint:0.25, 0.075
color:0.969, 0.463, 0.333, 1
background_color: 0.17, 0.55, 0.92, 1
<MainPage>
name: "MainPage"
FloatLayout:
Widget:
canvas:
Color:
rgb:0.969, 0.463, 0.333, 1
Rectangle:
size:self.width, self.height
Color:
rgb:1, 1, 1, 1
Rectangle:
size:self.width * 0.95, self.height * 0.95
pos:root.center_x * 0.05, root.center_y * 0.05
Color:
rgb:0, 0.18, 0.361, 1
Rectangle:
size:self.width * 0.95, self.height / 10
pos:root.center_x * 0.05, root.center_y * 1.75
Image:
source:"/Users/Desktop/App_Files/doc.jpg"
size_hint:0.1, 0.1
pos_hint:{"x": 0.01, "top": 0.87}
Image:
source:"/Users/Desktop/App_Files/doc.jpg"
size_hint:0.1, 0.1
pos_hint:{"x": 0.895, "top": 0.87}
Button:
text:"Schools Applied to"
size_hint:0.3,0.1
pos_hint:{"x":0.07, "top":0.45}
on_release:
app.root.current = "SchoolsAppliedToPage"
root.manager.transition.direction = "down"
Button:
text:"Add/Edit School"
size_hint:0.3,0.1
pos_hint:{"x":0.07, "top":0.3}
on_release:
app.root.current = "NewEntryPage"
root.manager.transition.direction = "up"
Button:
text:"Add/Edit Travel"
size_hint:0.3,0.1
pos_hint:{"x":0.07, "top":0.15}
on_release:
Label:
text:"Medical School is hard enough...let's try and save every penny that we can!"
size_hint:0.1, 0.1
pos_hint:{"x":0.45, "top":0.98}
font_name:"/Users/Desktop/App_Files/DancingScript-Regular.otf"
font_size: (root.width + root.height) / 70
color:0.97, 0.97, 0.97, 1
<NewEntryPage>
name:"NewEntryPage"
addschool:addschool
costofsecondary:cos
addtravelexpenses:ate
FloatLayout:
Widget:
canvas:
Color:
rgb: 0, 0.18, 0.361, 1
Rectangle:
size: self.width, self.height
Color:
rgb: 0.97, 0.97, 0.97, 1
Rectangle:
pos: 0, root.center_y * 1.75
size: self.width, self.height/8
Color:
rgb: 0.97, 0.97, 0.97, 1
Rectangle:
size: self.width * 0.9, self.height * 0.78
pos: root.center_x * 0.1, root.center_y * 0.1
Color:
rgb: 0, 0.18, 0.361, 1
Rectangle:
size: self.width * 0.72, self.height / 11
pos: root.center_x * 0.28, root.center_y * 1.78
Color:
rgb: 0.969, 0.463, 0.333, 1
Rectangle:
size: self.width * 0.7, self.height / 14
pos: root.center_x * 0.3, root.center_y * 1.80
Label:
font_name:"/Users/Desktop/App_Files/Antonio-Bold.ttf"
size_hint:0.3, 0.3
pos_hint:{"x":0.37, "top":0.93}
text:"Add School"
color:0.063, 0.024, 0.60, 1
TextInput:
id:addschool
size_hint:0.3, 0.1
pos_hint:{"x":0.37, "top": 0.75}
multinline:False
Label:
font_name:"/Users/Desktop/App_Files/Antonio-Bold.ttf"
size_hint:0.3, 0.3
pos_hint:{"x":0.37, "top":0.73}
text:"Cost Of Secondary"
color:0.063, 0.024, 0.60, 1
TextInput:
id:cos
size_hint:0.3, 0.1
pos_hint:{"x":0.37, "top": 0.55}
multinline:False
Label:
font_name:"/Users/Desktop/App_Files/Antonio-Bold.ttf"
size_hint:0.3, 0.3
pos_hint:{"x":0.37, "top":0.53}
text:"Add Travel Expenses"
color:0.063, 0.024, 0.60, 1
TextInput:
id:ate
size_hint:0.3, 0.1
pos_hint:{"x":0.37, "top": 0.35}
multinline:False
Button:
id:btn
text: "Submit" if btn.state == "normal" else "Done!"
pos_hint:{"x":0.395, "top":0.20}
on_press:root.pressBtn()
Image:
source:"/Users/Desktop/App_Files/med.png"
size_hint:0.1, 0.1
pos_hint:{"top": 0.99}
Image:
source:"/Users/Desktop/App_Files/med.png"
size_hint:0.1, 0.1
pos_hint:{"x":0.9, "top":0.99}
Label:
text:"Medical School is hard enough...let's try and save every penny that we can!"
size_hint:0.1, 0.1
pos_hint:{"x":0.45, "top":0.99}
font_name:"/Users/Desktop/App_Files/DancingScript-Regular.otf"
font_size: (root.width + root.height) / 70
color:0, 0.18, 0.361, 1
Button:
text:"Home"
pos_hint:{"x":0.13, "top":0.80}
size_hint:0.1, 0.05
on_release:
app.root.current = "MainPage"
root.manager.transition.direction = "down"
<SchoolsAppliedToPage>
name:"SchoolsAppliedToPage"
rvlist:rvlist
BoxLayout:
orientation: "vertical"
size_hint_y: 0.5
RecycleView:
id:rvlist
data:[{'text': school} for school in root.ListOfSchools]
viewclass:'Label'
RecycleGridLayout:
default_size: 100, 100
default_size_hint: 100, 100
size_hint_y:None
height: 500
orientation: 'vertical'
multiselect: True
touch_multiselect: True
cols: 4
Button:
text:"Home"
size_hint:0.3,0.1
pos_hint:{"x":0.07, "top":0.75}
on_release:
app.root.current = "MainPage"
root.manager.transition.direction = "up"
.txt
Harvard;$100;$100;
The app runs and displays, but when I try to update the list after a user submission I get this error: ph = item.get('pos_hint', ph) AttributeError: 'list' object has no attribute 'get'
In your pressBtn()
method of NewEntryPage
, the line:
SchoolsAppliedToPage().updatelist("/Users/PycharmProjects/msft/schools.txt", self.ListOfSchools)
is creating a new instance of SchoolsAppliedToPage
, and calling updatelist()
on that new instance. Unfortunately, that new instance is not the one that is in your GUI, so that code has no effect on what you see on the screen.
Try replacing that line with something like:
satp = App.get_running_app().root.get_screen('SchoolsAppliedToPage')
satp.updatelist("/Users/PycharmProjects/msft/schools.txt", self.ListOfSchools)
This code gets a reference to the instance of SchoolsAppliedToPage
, then calls updatelist()
on that instance.
Disclaimer: I have not tested the above code, but I believe that it suggests a correct approach.