Posts: 12,024
Threads: 484
Joined: Sep 2016
Capture responses, and save to a file.
add to ChoiceMade function
I have to move on, we have between 15,000 and 19,000 visitors each day, not everyone posts,
but it's still tough keeping up. Only about a dozen of us to answer all.
Posts: 23
Threads: 1
Joined: Apr 2019
No problem thanks for all your help
Posts: 12,024
Threads: 484
Joined: Sep 2016
I'll take a look at it now. Be back soon
Posts: 12,024
Threads: 484
Joined: Sep 2016
I have added a student info class, store the DataEntry.py script in same directory as quiz.py script.
This isn't quite how I think it should be, I'll work on it when I have time, also, the information
isn't saved anywhere yet. I'll incorporate that into the file that stores quiz results (again as I find time).
So you will be getting this piece meal
** NOTE ** There are changes to quiz.py to load new class.
DataEntry.py:
import tkinter as tk
class GetStudentInfo:
def __init__(self, parent):
self.fields = ['Student Id', 'Last Name', 'First Name', 'Date']
self.entry_widgets = []
self.parent = parent
self.parent.geometry('600x400+100+100')
self.parent.title('Student Information')
self.entry_widgets = self.create_form()
def get_entries(self, entry_widgets):
content = []
for element in entry_widgets:
field = element[0]
content.append(element[1].get())
return content
def create_form(self):
entry_widgets = []
for field in self.fields:
bgcolor = '#ffcc99'
ent_frame = tk.Frame(self.parent, bg=bgcolor, padx=2, pady=2, relief=tk.RAISED)
ent_label = tk.Label(ent_frame, bg=bgcolor, width=15, padx=2, pady=2, text=field, anchor='w')
ent_entry = tk.Entry(ent_frame, relief=tk.SUNKEN)
ent_frame.pack(side=tk.TOP, fill=tk.X, padx=5, pady=5)
ent_label.pack(side=tk.LEFT)
ent_entry.pack(side=tk.RIGHT, expand=True, fill=tk.X)
entry_widgets.append([field, ent_entry])
subbtn = tk.Button(self.parent, padx=2, pady=2, text='Submit', command=self.GetData)
subbtn.pack(side=tk.TOP)
return entry_widgets
def GetData(self):
content = self.get_entries(self.entry_widgets)
for n, field in enumerate(self.fields):
print(f'{field}: {content[n]}')
self.parent.destroy()
def main():
root = tk.Tk()
GetStudentInfo(root)
root.mainloop()
if __name__ == '__main__':
main() Quiz.py:
import tkinter as tk
import tkinter.ttk as ttk
import sqlite3
import os
import DataEntry
from pathlib import Path
import sys
class QuizGui:
def __init__(self, parent, title='Generic Title'):
# create directory anchor
os.chdir(os.path.abspath(os.path.dirname(__file__)))
homepath = Path('.')
datadir = homepath / 'QuestionsDatabase'
self.database = datadir / 'Questions.db'
self.parent = parent
self.get_student_info = DataEntry.GetStudentInfo(self.parent)
self.dbcon = None
self.db_connect()
self.question = None
self.choices = None
self.answer = None
self.current_question = 1
self.question_text = tk.StringVar()
self.rb_control = tk.StringVar()
self.rb_control.set('A')
self.rb = {}
self.youranswer = tk.StringVar()
self.youranswer.set('Please make choice, press select when ready')
self.rbval = []
self.parent.geometry('600x400+50+50')
self.parent.title(title)
self.build_gui()
def build_gui(self):
frame1 = tk.Frame(self.parent, bd=5, relief=tk.SUNKEN, padx=5, pady=5)
frame1.pack(fill=tk.BOTH)
qlabel = tk.Label(frame1, textvariable=self.question_text)
qlabel.pack(anchor='w')
self.get_next_question()
self.question_text.set(f'{self.current_question} {self.question}')
rb = self.rb = {}
for n, choice in enumerate(self.choices):
rb[n] = {}
rb[n]['txt'] = tk.StringVar()
rb[n]['txt'].set(f'{choice[0]} {choice[1]}')
rb[n]['val'] = tk.StringVar()
rb[n]['widget'] = tk.Radiobutton(frame1, textvariable=rb[n]['txt'], padx=5,
variable=self.rb_control, value=n)
rb[n]['widget'].pack(anchor='w')
frame2 = tk.Frame(frame1, height=5, bg='gray', padx=10, pady=10, relief=tk.RAISED)
frame2.pack(fill=tk.BOTH)
btn1 = tk.Button(frame1, text='Select', bd=2, relief=tk.RAISED,
padx=5, pady=5, width=25, command=self.ChoiceMade)
btn1.pack(anchor='w')
btn2 = tk.Button(frame1, text='Next Question', bd=2, relief=tk.RAISED,
padx=5, pady=5, width=25, command=self.set_next_question)
btn2.pack(anchor='w')
btn3 = tk.Button(frame1, text='Quit', bd=2, relief=tk.RAISED,
padx=5, pady=5, width=25, command=self.quit)
btn3.pack(anchor='w')
frame3 = tk.Frame(frame1, height=5, bg='gray', padx=10, pady=10, relief=tk.RAISED)
frame3.pack(fill=tk.BOTH)
response = tk.Label(frame1, textvariable=self.youranswer)
response.pack(anchor='w')
def set_next_question(self):
self.current_question += 1
self.get_next_question()
self.question_text.set(f'{self.current_question} {self.question}')
for n, choice in enumerate(self.choices):
self.rb[n]['txt'].set(f'{choice[0]} {choice[1]}')
def get_next_question(self):
question_number = self.current_question
self.question, self.choices, self.answer = self.get_current_question()
self.question_text.set(self.question)
def ChoiceMade(self):
item_index = int(self.rb_control.get())
if self.choices[item_index][0] == self.answer:
self.youranswer.set('Correct Answer')
else:
self.youranswer.set('Sorry Wrong Answer')
def db_connect(self):
try:
self.dbcon = sqlite3.connect(self.database)
except sqlite3.Error as e:
print(e)
def get_current_question(self):
question_number = self.current_question
qsql = f''' SELECT Question FROM Questions WHERE QuestionId = '{question_number}' '''
csql = f''' SELECT SeqLetter, Choice FROM Choices WHERE QuestionId = '{question_number}' ORDER BY SeqLetter '''
asql = f''' SELECT Answer FROM Answers WHERE QuestionId = '{question_number}' '''
try:
cursor = self.dbcon.cursor()
cursor.execute(qsql)
question = cursor.fetchone()[0]
choices = []
cursor.execute(csql)
while True:
choice = cursor.fetchmany()
if not len(choice):
break
choices.append(list(choice[0]))
cursor.execute(asql)
answer = cursor.fetchone()[0]
return question, choices, answer
except TypeError:
print(f'Invalid question_number {question_number}')
def quit(self):
self.db_close()
self.parent.destroy()
sys.exit(0)
def db_close(self):
self.dbcon.close()
if __name__ == '__main__':
root = tk.Tk()
QuizGui(root, title='Quiz Program')
root.mainloop()
Posts: 23
Threads: 1
Joined: Apr 2019
Okay, thanks again and again for all your help I'm wouldn't have been able to do this without you. When you send the newest changes could you again include how you did it, so I can learn to do it myself?
Posts: 18
Threads: 2
Joined: Nov 2021
there is a problem in quiz.py file when I run it it is not creating any gui
(Apr-15-2019, 11:12 AM)Larz60+ Wrote: I have added a student info class, store the DataEntry.py script in same directory as quiz.py script.
This isn't quite how I think it should be, I'll work on it when I have time, also, the information
isn't saved anywhere yet. I'll incorporate that into the file that stores quiz results (again as I find time).
So you will be getting this piece meal
** NOTE ** There are changes to quiz.py to load new class.
DataEntry.py:
import tkinter as tk
class GetStudentInfo:
def __init__(self, parent):
self.fields = ['Student Id', 'Last Name', 'First Name', 'Date']
self.entry_widgets = []
self.parent = parent
self.parent.geometry('600x400+100+100')
self.parent.title('Student Information')
self.entry_widgets = self.create_form()
def get_entries(self, entry_widgets):
content = []
for element in entry_widgets:
field = element[0]
content.append(element[1].get())
return content
def create_form(self):
entry_widgets = []
for field in self.fields:
bgcolor = '#ffcc99'
ent_frame = tk.Frame(self.parent, bg=bgcolor, padx=2, pady=2, relief=tk.RAISED)
ent_label = tk.Label(ent_frame, bg=bgcolor, width=15, padx=2, pady=2, text=field, anchor='w')
ent_entry = tk.Entry(ent_frame, relief=tk.SUNKEN)
ent_frame.pack(side=tk.TOP, fill=tk.X, padx=5, pady=5)
ent_label.pack(side=tk.LEFT)
ent_entry.pack(side=tk.RIGHT, expand=True, fill=tk.X)
entry_widgets.append([field, ent_entry])
subbtn = tk.Button(self.parent, padx=2, pady=2, text='Submit', command=self.GetData)
subbtn.pack(side=tk.TOP)
return entry_widgets
def GetData(self):
content = self.get_entries(self.entry_widgets)
for n, field in enumerate(self.fields):
print(f'{field}: {content[n]}')
self.parent.destroy()
def main():
root = tk.Tk()
GetStudentInfo(root)
root.mainloop()
if __name__ == '__main__':
main() Quiz.py:
import tkinter as tk
import tkinter.ttk as ttk
import sqlite3
import os
import DataEntry
from pathlib import Path
import sys
class QuizGui:
def __init__(self, parent, title='Generic Title'):
# create directory anchor
os.chdir(os.path.abspath(os.path.dirname(__file__)))
homepath = Path('.')
datadir = homepath / 'QuestionsDatabase'
self.database = datadir / 'Questions.db'
self.parent = parent
self.get_student_info = DataEntry.GetStudentInfo(self.parent)
self.dbcon = None
self.db_connect()
self.question = None
self.choices = None
self.answer = None
self.current_question = 1
self.question_text = tk.StringVar()
self.rb_control = tk.StringVar()
self.rb_control.set('A')
self.rb = {}
self.youranswer = tk.StringVar()
self.youranswer.set('Please make choice, press select when ready')
self.rbval = []
self.parent.geometry('600x400+50+50')
self.parent.title(title)
self.build_gui()
def build_gui(self):
frame1 = tk.Frame(self.parent, bd=5, relief=tk.SUNKEN, padx=5, pady=5)
frame1.pack(fill=tk.BOTH)
qlabel = tk.Label(frame1, textvariable=self.question_text)
qlabel.pack(anchor='w')
self.get_next_question()
self.question_text.set(f'{self.current_question} {self.question}')
rb = self.rb = {}
for n, choice in enumerate(self.choices):
rb[n] = {}
rb[n]['txt'] = tk.StringVar()
rb[n]['txt'].set(f'{choice[0]} {choice[1]}')
rb[n]['val'] = tk.StringVar()
rb[n]['widget'] = tk.Radiobutton(frame1, textvariable=rb[n]['txt'], padx=5,
variable=self.rb_control, value=n)
rb[n]['widget'].pack(anchor='w')
frame2 = tk.Frame(frame1, height=5, bg='gray', padx=10, pady=10, relief=tk.RAISED)
frame2.pack(fill=tk.BOTH)
btn1 = tk.Button(frame1, text='Select', bd=2, relief=tk.RAISED,
padx=5, pady=5, width=25, command=self.ChoiceMade)
btn1.pack(anchor='w')
btn2 = tk.Button(frame1, text='Next Question', bd=2, relief=tk.RAISED,
padx=5, pady=5, width=25, command=self.set_next_question)
btn2.pack(anchor='w')
btn3 = tk.Button(frame1, text='Quit', bd=2, relief=tk.RAISED,
padx=5, pady=5, width=25, command=self.quit)
btn3.pack(anchor='w')
frame3 = tk.Frame(frame1, height=5, bg='gray', padx=10, pady=10, relief=tk.RAISED)
frame3.pack(fill=tk.BOTH)
response = tk.Label(frame1, textvariable=self.youranswer)
response.pack(anchor='w')
def set_next_question(self):
self.current_question += 1
self.get_next_question()
self.question_text.set(f'{self.current_question} {self.question}')
for n, choice in enumerate(self.choices):
self.rb[n]['txt'].set(f'{choice[0]} {choice[1]}')
def get_next_question(self):
question_number = self.current_question
self.question, self.choices, self.answer = self.get_current_question()
self.question_text.set(self.question)
def ChoiceMade(self):
item_index = int(self.rb_control.get())
if self.choices[item_index][0] == self.answer:
self.youranswer.set('Correct Answer')
else:
self.youranswer.set('Sorry Wrong Answer')
def db_connect(self):
try:
self.dbcon = sqlite3.connect(self.database)
except sqlite3.Error as e:
print(e)
def get_current_question(self):
question_number = self.current_question
qsql = f''' SELECT Question FROM Questions WHERE QuestionId = '{question_number}' '''
csql = f''' SELECT SeqLetter, Choice FROM Choices WHERE QuestionId = '{question_number}' ORDER BY SeqLetter '''
asql = f''' SELECT Answer FROM Answers WHERE QuestionId = '{question_number}' '''
try:
cursor = self.dbcon.cursor()
cursor.execute(qsql)
question = cursor.fetchone()[0]
choices = []
cursor.execute(csql)
while True:
choice = cursor.fetchmany()
if not len(choice):
break
choices.append(list(choice[0]))
cursor.execute(asql)
answer = cursor.fetchone()[0]
return question, choices, answer
except TypeError:
print(f'Invalid question_number {question_number}')
def quit(self):
self.db_close()
self.parent.destroy()
sys.exit(0)
def db_close(self):
self.dbcon.close()
if __name__ == '__main__':
root = tk.Tk()
QuizGui(root, title='Quiz Program')
root.mainloop()
|