Reputation: 45
I'm attempting to create a simple multiple choice quiz in Tkinter. The goal is to have multiple quiz categories with multiple questions in each category. To do that I am attempting to use use named tuples which I pass to a quiz class and methods. When I run the program, I get the following traceback message:
Traceback (most recent call last):
File "/home/daniel/pythonfiles/tkquizradio.py", line 124, in <module>
app = SimpleTkinter()
File "/home/daniel/pythonfiles/tkquizradio.py", line 31, in __init__
frame = F(house, self)
TypeError: __init__() takes 2 positional arguments but 3 were given
What's weird is that prior to editing the MathQuiz class and attempting to create the buttons and getDecision method, I was not receiving this error. The initial frame displayed fine and I was able to select which quiz I wanted. Really not sure why this is happening. If you have any advice for me, regarding this problem it is much appreciated.
"""import any necessary modules"""
import tkinter as tk
from collections import namedtuple
from tkinter import *
qtuple = namedtuple("question", "question, correct")
atuple = namedtuple("answer", "answer1, answer2, answer3, answer4")
FONT = ("Verdana", 12)
""""create tkinter frames"""
class SimpleTkinter(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
house = tk.Frame(self)
house.pack(side = "top", fill = "both", expand = True)
house.grid_rowconfigure(0, weight = 1)
house.grid_columnconfigure(0, weight = 1)
self.frames = {}
for F in (StartPage, QuizChoice, MathQuiz):
frame = F(house, self)
self.frames[F] = frame
frame.grid(row = 0, column = 0, sticky = "nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
"""create startpage"""
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text = "Multiple Choice Quiz", font=FONT)
label.pack(pady=10,padx=10)
startbutton = tk.Button(self, text="Click to start quiz",
command=lambda: controller.show_frame(QuizChoice))
startbutton.pack()
"""main logic"""
class QuizChoice(tk.Frame):
def __init__(self, parent, controller):
"""get input""""
tk.Frame.__init__(self, parent)
v = tk.IntVar()
label = tk.Label(self, text = "Please choose a category:", justify = tk.LEFT,font = FONT)
label.pack(pady=10, padx=10)
button1 = tk.Radiobutton(self, text="Math", variable=v, value=1,
command=lambda: controller.show_frame(MathQuiz))
button1.pack()
button2 = tk.Radiobutton(self, text="Animals", variable=v, value=2)
button2.pack()
button3 = tk.Radiobutton(self, text="History", variable=v, value=3)
button3.pack()
"""def different quizzes"""
class MathQuiz(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
v = tk.IntVar()
"""create label containing question"""
"""create radiobuttons with options"""
"""set score"""
score = 0
quiz = [qtuple("What is 1 + 4", {"5"}), """"..."""]
answers = [atuple("3", "4", "5", "6")]
for question in quiz:
label1 = tk.Label(self, text=question.question, font=FONT)
label1.pack(pady=10, padx=10)
for answer in answers:
button1 = tk.Radiobutton(self, text=answer.answer1, variable=answer.answer1, value=1)
button1.pack()
button2 = tk.Radiobutton(self, text=answer.answer2, variable=v, value=2)
button2.pack()
button3 = tk.Radiobutton(self, text=answer.answer3, variable=v, value=3)
button3.pack()
submit = tk.Button(self, text='Submit', command=getDecision)
submit.grid()
def getDecision(self):
if v.get() == quiz.correct:
messagebox.showinfo('Congrats', message='You Are Correct.Score is {}'.format(score))
else:
messagebox.showinfo('Lose', message='You Are Wrong.')
class history_quiz():
questions = [qtuple("What is", "answer", ["choices"], {"correct"})]
class animal_quiz():
questions = [qtuple("What is", "answer", ["choices"], {"correct"})]
app = SimpleTkinter()
app.mainloop()
Upvotes: 0
Views: 41
Reputation: 366003
Your first two frame classes take three parameters:
class StartPage(tk.Frame):
def __init__(self, parent, controller):
class QuizChoice(tk.Frame):
def __init__(self, parent, controller):
… but your last one only takes two:
class MathQuiz(tk.Frame):
def __init__(self, parent):
An __init__
method is just like any other method—it can only take the arguments you declared it to take. When you try to construct a MathQuiz
with that extra argument, it has no idea what to do with it, so it complains.
The smallest fix is to just add another parameter, so it matches the other classes:
class MathQuiz(tk.Frame):
def __init__(self, parent, controller):
Now they all have the same signature, so they can all be used the same way, so your code will work. The fact that you have nothing useful to do with that controller
doesn't mean you can't take it as a parameter and just ignore it.
Upvotes: 2