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
#21
Looking at the code you posted, it can't possibly run as presented.

Use a drawing program to show how you want this to look and post.
Or if at some point you had it running, post a screenshot of what you want it to look like.
Reply
#22
Here are the screeen shots of the program working

Attached Files

Thumbnail(s)
       
Reply
#23
Well, I didn't go to sleep yet, been up since 4:00 AM EST yesterday 27.5 hours.
I went ahead and designed as I saw fit, this code is almost done, next question not yet working.
Don't know when I'll wake after pushing myself, but will get it working then.
At that point, I'll leave it up to you to add any embellishments and/or additions
Dont' forget to run the database creation program first

Here's current code and screenshot
import tkinter as tk
import tkinter.ttk as ttk
import sqlite3
import os
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.dbcon = None
        self.db_connect()
        
        self.choices = None
        self.answer = None
        self.next_question = 1

        self.youranswer = tk.StringVar()
        self.current_question = tk.StringVar()
        self.current_choice = tk.StringVar()
        self.answer_disp = tk.StringVar()
        self.current_choice.set('A')
        
        parent.geometry('600x400+50+50')
        parent.title(title)

        self.build_gui(parent)
        self.db_close()
    
    def build_gui(self, parent):
        frame1 = tk.Frame(parent, bd=5, relief=tk.SUNKEN, padx=5, pady=5)
        frame1.pack(fill=tk.BOTH)
        qlabel = tk.Label(frame1, textvariable=self.current_question)
        qlabel.pack(anchor='w')
        self.get_next_question()
        for choice in self.choices:
            choiceid = choice[0]
            choice_text = choice[1]
            choiceval = f'{choiceid}     {choice_text}'
            rb = tk.Radiobutton(frame1, 
                  text=choiceval,
                  padx = 10, 
                  variable=self.current_choice, 
                  value=choiceid)
            rb.pack(anchor=tk.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, command=self.ChoiceMade)
        btn1.pack(anchor='w')
        btn2 = tk.Button(frame1, text='Next Question', bd=2, relief=tk.RAISED, 
            padx=5, pady=5, command=self.ChoiceMade)
        btn2.pack(anchor='w')
        response = tk.Label(frame1, textvariable=self.get_next_question)
        response.pack(anchor='w')            

    def get_next_question(self):
        question_number = self.next_question
        question, self.choices, self.answer = self.get_question(question_number)
        # print(f'question: {question}, self.choices: {self.choices}, answer: {self.answer}')
        self.current_question.set(f'Question {question_number}:     {question}')
        self.next_question += 1
        self.answer_disp.set('')

    def ChoiceMade(self):
        if self.current_choice.get() == 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_question(self, 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:
            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 db_close(self):
        self.dbcon.close()

if __name__ == '__main__':
    root = tk.Tk()
    QuizGui(root, title='Quiz Program')
    root.mainloop()
   
Reply
#24
You are incredible! Thank you so much for your help, thanks for your advice I will try running it now.
Reply
#25
Ok,
Looks like all is working, so here's the code, and a final screenshot.
You should be able to take control from here and make any modifications you need.
Play with it, if you mess it up, no problem, you can always come back here and start over.

code:
import tkinter as tk
import tkinter.ttk as ttk
import sqlite3
import os
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.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()
Final screenshot:
   
Reply
#26
Thank you so much you are amazing

Hi ive been playing around with the program I want to implement a log in page to visit before the quiz.
Where do I place the code to get the window to open
Reply
#27
?? perhaps a new logger class with a method named log,
then you can instantiate in the QuizGui __init__ method as logger = loggerclassname(), and just call
loggetclassname.log() to make an entry into the log.
Reply
#28
Hi, sorry to ask this but how would i implement that
Reply
#29
Show how you think you would do that, and we will help.
Reply
#30
I have no experience with this I dont know where to start
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  PyQt5 form not displaying my data from SQLite3 Database Linuxdesire 2 4,989 Jan-10-2023, 09:51 PM
Last Post: gradlon93
  Can't get tkinter database aware cascading comboboxes to update properly dford 6 3,657 Jan-11-2022, 08:37 PM
Last Post: deanhystad
Question [Tkinter] data enterred through gui is not storing in sqlite3 database Hilal 21 7,609 Dec-15-2021, 08:48 PM
Last Post: Hilal
  Help with PySimpleGUI INSERT INTO sqlite3 database jrbond 5 7,183 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,677 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