Python Forum
[Tkinter] TKINTER quiz using sqlite3 database
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Tkinter] TKINTER quiz using sqlite3 database
#31
Start by writing down what you want the logger to do, step by step.
Reply
#32
import tkinter as tk
import tkinter.ttk as ttk
import sqlite3
import os
from pathlib import Path
import sys
from tkinter import *


 
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.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):
        ##root.destroy()
        ##root = tk.Tk()
        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()

def login():
    root =Tk()
    l1 = Label(root, text='User: ')
    l2 = Label(root, text='password: ')
    t1=Entry(root, textvariable=StringVar())
    t2=Entry(root, show= '*', textvariable=StringVar())

    def valid():
        u=t1.get()
        p=t2.get()
        if (u=='admin') and (p=='admin'):
            l4 = Label(root, text='Welcome Admin - Hello All')
            l4.pack()
            if __name__ == '__main__':
                QuizGui(root, title='Quiz Program')
                root.mainloop()



        else:
            l3 = Label(root, text='Invalid Username and Password')
            l3.pack()

    b1=Button(root, text= 'Log-in', command=valid)
    l1.pack()
    t1.pack()
    l2.pack()
    t2.pack()
    b1.pack()


login()
Hi I have the log in working but i cant clear the GUI after the log in is finished can you help with this?
Reply
#33
Hi, also could you add some notation from your original code? There are some parts that I don't understand, as I want to understand what it is you did to make it work?

id like to know how you completed it so I can learn to replicate it myself in future circumstances
Reply
#34
I'd be glad to, but Which parts? as I don't have a lot of time.
Reply
#35
I have sufficient knowledge of Tkinter gui's but Id like to know how you called the questions from the database and then connected them to each of the buttons
Reply
#36
Also, at which part of the code could I output the results of the quiz into a textfile
Reply
#37
the database has three tables, Question, Choices and Answers
If you run sqlite3 from command line, you can see the different tables:
SQLite version 3.11.0 2016-02-15 17:29:24
Enter ".help" for usage hints.
sqlite> .schema
CREATE TABLE Questions (QuestionId, QuizCode, Unused, Question);
CREATE TABLE Choices (QuestionId, QuizCode, SeqLetter, Choice);
CREATE TABLE Answers (QuestionId, QuizCode, Answer, Unused);
As you can see, each table has QuestionId in common, yo you can link everything together using that:
sqlite> select * from Questions where QuestionId = '1';
1|Q||Which Of these describes an element best?
sqlite>
sqlite> select * from choices where QuestionId = '1';
1|C|A|Building Block
1|C|B|Made Of Only One Type Of Atom
1|C|C|Contains No Chemical Bonds
1|C|D|Pure Substance
sqlite>
sqlite> 
sqlite> select * from answers where QuestionId = '1';
1|A|B|
sqlite>
The second column contains the quiz code (same as spreadsheet, Q, C or A for question, choice, or answer)


def get_question(self, question_number):
        # Set up SQL statements (based on question_number)
        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:
            # create a cursor
            cursor = self.dbcon.cursor()
            # fetch question using SQL statement qsql
            cursor.execute(qsql)
            # fetch result of query into variable question
            question = cursor.fetchone()[0]

            # Create a list to hold all choices
            choices = []
            # fetch choices using SQL statement csql
            cursor.execute(csql)
            # move results into choices list
            while True:
                choice = cursor.fetchmany()
                if not len(choice):
                    break
                choices.append(list(choice[0]))

            # fetch answer using SQL statement asql
            cursor.execute(asql)
            # fetch result of query into variable answer
            answer = cursor.fetchone()[0]
            return question, choices, answer
        except TypeError:
            print(f'Invalid question_number {question_number}')
Variables are set from the query
for example line 39:
qlabel = tk.Label(frame1, textvariable=self.current_question)
uses textvariable self.current_question which is set on line 69:
self.current_question.set(f'Question {question_number}: {question}')

the others are similar
on line 62:
response = tk.Label(frame1, textvariable=self.get_next_question)
textvariable is self.get_next_question
Reply
#38
Okay, thank you very much, any suggestions on how I can export the results. What part of the code should I go to output them?
Reply
#39
I'm not sure of what you mean by export results?
Reply
#40
I want to have a document with a record of how the user answered the questions and weather or not they were correct
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  PyQt5 form not displaying my data from SQLite3 Database Linuxdesire 2 4,987 Jan-10-2023, 09:51 PM
Last Post: gradlon93
  Can't get tkinter database aware cascading comboboxes to update properly dford 6 3,650 Jan-11-2022, 08:37 PM
Last Post: deanhystad
Question [Tkinter] data enterred through gui is not storing in sqlite3 database Hilal 21 7,589 Dec-15-2021, 08:48 PM
Last Post: Hilal
  Help with PySimpleGUI INSERT INTO sqlite3 database jrbond 5 7,176 Jul-20-2020, 01:24 PM
Last Post: jrbond
  sQlite3 output to tkinter treeview - how do I set / increase width of the output? dewijones67 5 6,669 Jan-23-2019, 08:45 AM
Last Post: Larz60+

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020