I’m quite new to Kivy and have been repeatedly having issues with displaying things. I am building a basic app to track students, assign them to school houses (like in Harry Potter) and display them. I created a “for” loop to add users to labels in a stack layout which would then display them in a scroll view, but for some reason, when I run the file, nothing is displayed. I have no idea what is going on. Please run the file yourself, to troubleshoot the problem
Note: The problem concerns lines 261-280 in the python file
Python file:
from os.path import join from random import random, choice from kivy.app import App from kivy.config import Config Config.set('graphics', 'width', '400') Config.set('graphics', 'height', '600') from kivy.storage.jsonstore import JsonStore from kivy.uix.screenmanager import ScreenManager, Screen from kivy.uix.floatlayout import FloatLayout from kivy.uix.gridlayout import GridLayout from kivy.uix.textinput import TextInput from kivy.uix.widget import Widget from kivy.uix.label import Label from kivy.uix.button import Button from kivy.uix.checkbox import CheckBox from kivy.uix.popup import Popup from kivy.lang import Builder from kivy.uix.boxlayout import BoxLayout from kivy.uix.anchorlayout import AnchorLayout from kivy.uix.stacklayout import StackLayout from kivy.uix.scrollview import ScrollView from kivy.uix.dropdown import DropDown from kivy.metrics import dp from kivy.properties import ObjectProperty, StringProperty, BooleanProperty, Clock from kivy.graphics.vertex_instructions import Line, Rectangle, Ellipse from kivy.graphics.context_instructions import Color from kivy.core.window import Window class LoginScreen(Screen): #This screen is the first window displayed when the program runs developer_version = StringProperty('1.0.0') #Incriment with each software update/patch. Patch ex.: 1.0.1 and Update ex.: 1.1.0 email = ObjectProperty(None) #Email variable which will recieve text data from Kivy password = ObjectProperty(None) #Password variable which will recieve text data from Kivy id_credentials = None #A variabled used to identify which password file the user has sign in through id_name = {} #A dict used to assign the user an id based off which password file they sign in through remember_login_user = None #A (to be) boolean used to determine whether the user wants to remember their login data user_found_line = None #Identifies what line the user's data appeared in their respective password file specific_house = '' #A stringed int for which house the user has selected check_box_cond = ObjectProperty(None) #Checks whether the "remeber login" checkbox is active index_count = 0 #Keeps track of what line login credentials are on cred_name = '' #Stores the user's login data that is within the ..._user dict passwordStudents = open('passwords/passwordStudents.txt', 'r') #40-43 all read the login text files used to check if login credentials are correct passwordTeachers = open('passwords/passwordTeachers.txt', 'r') passwordAdmin = open('passwords/passwordAdmin.txt', 'r') #student_char_creds = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '@', '.'] <--- Likely won't need this student_user = {} teacher_user = {} admin_user = {} for i in passwordStudents: first, last, email, password = i.strip().split(';') student_user[f'{first} {last}'] = (email, password) for i in passwordTeachers: first, last, email, password = i.strip().split(';') teacher_user[f'{first} {last}'] = (email, password) for i in passwordAdmin: first, last, email, password = i.strip().split(';') admin_user[f'{first} {last}'] = (email, password) passwordStudents.close() passwordTeachers.close() passwordAdmin.close() def loginBtn(self): #Checks eamil and password to assess whether user credentials are correct and if said user is a student, teacher, or admin login_email = self.email.text login_password = self.password.text login_lst = self.email.text + ', ' + self.password.text su = False tu = False au = False for i in self.student_user.values(): if login_email in i: self.cred_name = i if i[0] + ', ' + i[1] == login_lst: su = True login_lst = '' self.id_credentials = 'Student' self.user_cred(self.student_user) self.reset() self.home() else: su = True self.reset() self.login_error() self.index_count += 1 for i in self.teacher_user.values(): if login_email in i: self.cred_name = i if i[0] + ', ' + i[1] == login_lst: tu = True login_lst = '' self.id_credentials = 'Teacher' self.user_cred(self.teacher_user) self.reset() self.home() else: tu = True self.reset() self.login_error() self.index_count += 1 for i in self.admin_user.values(): if login_email in i: self.cred_name = i if i[0] + ', ' + i[1] == login_lst: au = True login_lst = '' self.id_credentials = 'Admin' self.user_cred(self.admin_user) self.reset() self.home() else: au = True self.reset() self.login_error() self.index_count += 1 if su == False: if tu == False: if au == False: self.reset() self.login_error() def reset(self): #Resets textinputs in login self.email.text = '' self.password.text = '' def home(self): #Redirects user to home window sm.transition.direction = 'up' sm.current = 'home' def login_error(self): #Handles login errors buttons = Button(text='Got It') labels = Label(text='Invalid username or password nn') grids = GridLayout(rows=2) grids.add_widget(labels) grids.add_widget(buttons) pop = Popup(title='Invalid Login', content=grids, size_hint=(None, None), size=(450, 450), auto_dismiss=False) buttons.bind(on_press=pop.dismiss) pop.open() def user_cred(self, cred): #Gives user an id key_lst = list(cred.keys()) val_lst = list(cred.values()) pos = val_lst.index(self.cred_name) self.id_name[key_lst[pos]] = self.id_credentials def remember_login(self): #Allows users to remeber their login data for the next time they login ''' a = list(str(open(f'passwords/password{self.id_credentials}.txt').readlines(self.user_found_line))) for i in range(2): a.pop(0) a.pop(-1) for i in range(2): a.pop(-1) b = ''.join(a) c = b.split(' ') remember_dir_file = c[-1] if remember_dir_file == 'True': self.email.text = ''' pass def check_if_box_active(self): #Allows users to access app without needing to sign in every time pass class HomeScreen(Screen): #The main page that the user is directed to def return_to_login_Btn(self): sm.transition.direction = 'down' sm.current = 'login' LoginScreen().id_name.clear() def check_user_id_1(self): if list(LoginScreen().id_name.values())[0] == 'Student': StudentsGridList().foo('1') sm.transition.direction = 'left' sm.current = 'studentHome' elif list(LoginScreen().id_name.values())[0] == 'Teacher': StudentsGridList().foo('1') sm.transition.direction = 'left' sm.current = 'teacherHome' elif list(LoginScreen().id_name.values())[0] == 'Admin': StudentsGridList().foo('1') sm.transition.direction = 'left' sm.current = 'adminHome' def check_user_id_2(self): if list(LoginScreen().id_name.values())[0] == 'Student': StudentsGridList().foo('2') sm.transition.direction = 'left' sm.current = 'studentHome' elif list(LoginScreen().id_name.values())[0] == 'Teacher': StudentsGridList().foo('2') sm.transition.direction = 'left' sm.current = 'teacherHome' elif list(LoginScreen().id_name.values())[0] == 'Admin': StudentsGridList().foo('2') sm.transition.direction = 'left' sm.current = 'adminHome' def check_user_id_3(self): if list(LoginScreen().id_name.values())[0] == 'Student': StudentsGridList().foo('3') sm.transition.direction = 'left' sm.current = 'studentHome' elif list(LoginScreen().id_name.values())[0] == 'Teacher': StudentsGridList().foo('3') sm.transition.direction = 'left' sm.current = 'teacherHome' elif list(LoginScreen().id_name.values())[0] == 'Admin': StudentsGridList().foo('3') sm.transition.direction = 'left' sm.current = 'adminHome' def check_user_id_4(self): if list(LoginScreen().id_name.values())[0] == 'Student': StudentsGridList().foo('4') sm.transition.direction = 'left' sm.current = 'studentHome' elif list(LoginScreen().id_name.values())[0] == 'Teacher': StudentsGridList().foo('4') sm.transition.direction = 'left' sm.current = 'teacherHome' elif list(LoginScreen().id_name.values())[0] == 'Admin': StudentsGridList().foo('4') sm.transition.direction = 'left' sm.current = 'adminHome' def foobar(self): sm.current = 'spec' class StudentSpecificHomeScreen(Screen): #Students can access their students' house pages def return_to_home_Btn(self): sm.transition.direction = 'right' sm.current = 'home' class TeacherSpecificHomeScreen(Screen): #Teachers can access their teachers' house pages def return_to_home_Btn(self): sm.transition.direction = 'right' sm.current = 'home' class AdminSpecificHomeScreen(Screen): #Admin can access their admins' house pages def return_to_home_Btn(self): sm.transition.direction = 'right' sm.current = 'home' class StudentsGridList(StackLayout): #Lists and orders students into a StackLayout def foo(self, specific_house): print(specific_house) if int(specific_house) == int: house_users = open(f'houses/house{specific_house}.txt', 'r') for user in house_users: user = user.split('n')[0] if user == 'Griffin Neal': user = f'[color=#000000][b]Dev:[/b] [color=#028A0F][i]{user}[/i]' else: user = f'[color=#000000]{user}' size = dp(150) labels = Label(text=user, size_hint=(None,None), size=(size, size), bold=True, markup=True) self.add_widget(labels) house_users.close() else: pass class StudentsList(ScrollView): #Lists all students in a scroll view pass def SortingHat(): #Admins can use this to randomly sort students into houses pass class WindowManager(ScreenManager): pass sm = WindowManager() class MyApp(App): def build(self): screens = [LoginScreen(name='login'), HomeScreen(name='home'), StudentSpecificHomeScreen(name='studentHome'), TeacherSpecificHomeScreen(name='teacherHome'), AdminSpecificHomeScreen(name='adminHome')] for screen in screens: sm.add_widget(screen) sm.current = 'login' Window.clearcolor = (230/255,230/255,230/255,1) return sm if __name__ == '__main__': MyApp().run()
Kivy file:
LoginScreen: <LoginScreen>: name: "login" email: email password: psswrd check_box_cond: checks BoxLayout: orientation: "vertical" canvas.before: Color: rgba: 1,1,1,1 Label: text: "Login" pos: 0, root.height/3 font_size: 100 color: 50/255,50/255,50/255,1 GridLayout: cols: 2 Label: size_hint: None, None width: "175dp" height: "50dp" text: "Email:" font_size: 50 color: 50/255,50/255,50/255,1 TextInput: id: email multiline: False size_hint: None, None width: "200dp" height: "50dp" font_size: (root.width**2 + root.height**2) / 14**4 GridLayout: cols: 2 Label: size_hint: None, None width: "175dp" height: "50dp" text: "Password:" font_size: 50 color: 50/255,50/255,50/255,1 TextInput: id: psswrd multiline: False size_hint: None, None width: "200dp" height: "50dp" password: True font_size: (root.width**2 + root.height**2) / 14**4 GridLayout: cols: 3 row_force_default: True row_default_height: "40" Label: text: "" size_hint_x: None width: "100dp" CheckBox: id: checks color: 0,0,0,1 size_hint_x: None width: "40dp" on_active: root.remember_login() Label: font_size: (root.width**2 + root.height**2) / 14**4 - 20 text: "Remeber sign in?" color: 50/255,50/255,50/255,1 size_hint_x: None width: "160dp" FloatLayout: Button: background_color: 1,1,1,1 size_hint: None, None width: "150dp" height: "100dp" pos: root.width/2 - 150, root.height/4 - 250 text: "Submit" font_size: (root.width**2 + root.height**2) / 14**4 color: 10/255,10/255,10/255,1 on_release: root.loginBtn() Label: size_hint: None, None width: "150dp" height: "100dp" pos: root.width/2 - 150, root.height/4 - 375 color: 10/255, 10/255, 10/255, 1 text: f"Version: {root.developer_version}" <HomeScreen>: name: "home" GridLayout: rows: 3 BoxLayout: size_hint: 1, 0.15 Label: text: "" Button: size_hint: 0.4, 1 text: "Logout" font_size: (root.width**2 + root.height**2) / 14**4 on_release: root.return_to_login_Btn() GridLayout: cols: 2 rows: 2 Button: text: "House 1" font_size: (root.width**2 + root.height**2) / 14**4 on_release: root.check_user_id_1() Button: text: "House 2" font_size: (root.width**2 + root.height**2) / 14**4 on_release: root.check_user_id_2() Button: text: "House 3" font_size: (root.width**2 + root.height**2) / 14**4 on_release: root.check_user_id_3() Button: text: "House 4" font_size: (root.width**2 + root.height**2) / 14**4 on_release: root.foobar() <StudentSpecificHomeScreen>: GridLayout: rows: 2 name: "studentHome" FloatLayout: size_hint: 1, None height: root.height/6 Button: pos: root.width/2 - root.width/4, root.height*3/4 + 85 size_hint: None, None width: root.width/2 height: "100dp" text: "Return Home" font_size: (root.width**2 + root.height**2) / 14**4 on_release: root.return_to_home_Btn() StudentsList: StudentsGridList: padding: ('20dp', '20dp', '20dp', '20dp') spacing: ('20dp', '20dp') size_hint: 1, None height: self.minimum_height <TeacherSpecificHomeScreen>: name: "teacherHome" GridLayout: rows: 2 Button: size_hint: None, None width: "175dp" height: "100dp" text: "Return Home" font_size: (root.width**2 + root.height**2) / 14**4 on_release: root.return_to_home_Btn() <AdminSpecificHomeScreen>: name: "adminHome" GridLayout: rows: 2 Button: size_hint: None, None width: "175dp" height: "100dp" text: "Return Home" font_size: (root.width**2 + root.height**2) / 14**4 on_release: root.return_to_home_Btn()
Fake student credentials text file (put it into a text file called “passwordStudents.txt” in a folder called “passwords”):
Griffin;Neal;griffin@taguspark.org;1234 Ela;Talor;ela1265@taguspark.org;4321 Lucas;Dore;lucas@taguspark.org;0987 Matilde;Obrien;matilde@taguspark.org;7890 Mia;McCabian;mia@gmail.com;9078 Eli;Cobbb;eli@gmail.com;6785 James;May;jame@gmail.com;4132 Connor;McCarren;connor@gmail.com;1626 Gabe;Newell;gaben@steam.com;0000
Student houses (create four text files with the students’ first and last names at random called “house1.txt”, “house2.txt”, etc. in a folder called “houses”)
Advertisement
Answer
A couple problems with your code:
- Everywhere you use code like
StudentsGridList().foo('4')
, you are creating a new instance ofStudentsGridList
and calling thefoo()
method of that new instance. Doing so will have no effect on theStudentsGridList
instance that is in theStudentSpecificHomeScreen
of your GUI. - The
if
statementif int(specific_house) == int:
in yourfoo()
method will always beFalse
, since your are comparing an integer to a built-in method.
To correct the first problem, you will probably need to use the get_screen() method of ScreenManager
along with some ids
in order to access the instance of StudentsGridList
that is actually in your GUI. You will probably need to assign an id
to the StudentsGridList
. This can be done in your kv
file:
StudentsList: StudentsGridList: id: sgl # added id padding: ('20dp', '20dp', '20dp', '20dp') spacing: ('20dp', '20dp') size_hint: 1, None height: self.minimum_height
Then, in your code you can replace:
StudentsGridList().foo('4')
with:
sm.get_screen('studentHome').ids.sgl.foo('4')
And similarly for the other occurrences of StudentsGridList().foo()
.
As for the second problem, I am not sure of the purpose of that if
statement. Perhaps that if
statement should just be removed.