How do I link imported questions with Imported answers? - python

I am a student at high-school and we are left to create a maths question answer game. We are given Questions and Answers in Excel to import into the program and it asks a random questions (from the ones given) and you have to be told if you have got the question correct or not.
I am stuck at this point where the program asks the question but I am unsure how to get the answer to match with the question given.
here is my code to see what I have done, any information helps.
csv_file = open("questions.csv", "r")
question_reader = csv.reader(csv_file, delimiter = ",")
for row in question_reader:
The_que = row[0]
The_ans = row[1]
self.questions.append(equation(The_que, The_ans))
csv_file.close()
for question in self.questions:
question.display()
from random import randint
ran_num = randint(0,20)
print(self.questions[ran_num].question)
random_question = (self.questions[ran_num].question)
self.label_1 = Label(parent, bg= "Black",
fg = "Pink",
text = random_question,
padx=30,
pady=10,
font =("times", "14", "bold " ))
self.label_1.pack()
self.button_1 = Button(parent,
text = "Lock in Answer",
command = self.Answer_entry)
self.button_1.pack()
self.entry_1 = Entry(parent)
self.entry_1.pack()
def Answer_entry(self):
the_text = self.entry_1.get()
self.label_1.configure(text = the_text)
So There is more to the code that I haven't linked but I think this will good to show. Right now I have
the_text
as a placeholder
. Reminder I am a High school student who started programming 3-5 weeks ago so please try to explain this like it is to a 5 year old since I am not great at this.

Related

Using guizero and a text datafile to create GUI

So I'm trying to help a student figure out how to create a simple quiz by reading from a text file with the questions, options, and answers. He wants to use guizero instead of the simple built-in input() and print() functions.
I would like him to avoid creating a separate check function for each question, but I don't have much experience with guizero. I've been reading the manual pages, and the below code approximates what we are trying to accomplish but doesn't work because selected_value is not defined until after the program runs. Am I approaching this the wrong way?
from guizero import App, Text, ButtonGroup
app = App(title="Quiz Test", height=800, width=600)
def check_answer(selected_value, answer):
if selected_value == answer:
result.value = "Correct"
else:
result.value = "Wrong"
question_data = []
data_file = open("quiz_ques.txt", 'r')
for line in data_file.read().splitlines():
question_data = line.split(", ")
question_data.reverse() ; question = question_data.pop()
question_data.reverse() ; answer = question_data.pop()
q_options = question_data
text = Text(app, text=question)
choice = ButtonGroup(app, options=q_options, selected=1, command=check_answer, args=[selected_value, answer])
result = Text(app)
data_file.close()
app.display()
try changing
command=check_answer()
to
command=check_answer
in the original version you were calling check_answer() as soon as you defined your program... in the second version it will not be called until the button is clicked
I figured this out using a couple of lists for anyone looking for a solution. Someone who is more of a python expert could probably simplify this, using some pythonic idiom, built-in functions, or standard modules, but this solution works even if it's a bit of a hack. Improvements on this are welcomed. :)
from guizero import App, Text, ButtonGroup
app = App(title="Quiz Test", height=800, width=600)
def check_answer(answer, result, cnt):
if choices[cnt].value == answer:
result.text_color = 'green'
result.value = "Correct"
update_score()
else:
result.text_color = 'red'
result.value = "Wrong"
update_score()
def update_score():
score = 0
for result in results:
if result.value == "Correct":
score += 1
score_txt.value = "Score: " + str(score)
question_data = []
data_file = open("quiz_ques.txt", 'r')
cnt = 0
results = []
choices = []
for line in data_file.read().splitlines():
question_data = line.split(", ")
question_data.reverse() ; question = question_data.pop()
question_data.reverse() ; answer = question_data.pop()
q_options = question_data
question = Text(app, text=question)
question.text_color = 'white'
results.append(Text(app))
choices.append(ButtonGroup(app, options=q_options, command=check_answer, args=[answer, results[cnt], cnt]))
cnt += 1
score_txt = Text(app, color='white', size=40)
data_file.close()
app.display()

Tkinter: multiple choice quiz app, can't change question (and other issues)

I'm trying to create a multiple choice question app with tkinter but I'm having three problems that I can't solve by myself:
The question don't change, it stuck on the first question.
I have a file with all my questions (more then 50) what I'd like to do is select randomly only 10 of them from the list (five from easy_question list and 5 from the hard_question list).
Is there a way to save in an exel file the ten code of the question that where selected and to know what that person answered (wrong or right doesn't metter)? something like this:
1 2 3 [...]
question 1e 3h 2e
answer 2 3 4
This is a simple version of my file with all my questions, options and correct answers:
easy_questions2=[
"1e. Name?",
"2e. Last name?",
"3e. Birthdate?",
"4e. Food?"
]
easy_options=[
['Marck', 'Mary','Joseph','John'],
['Smith', 'Hartnett','Pitt','Pacino'],
['June', 'October','November','April'],
['All', 'Fries','Pasta','Chicken']
]
easy_answers=[
1,
2,
3,
3
]
hard_questions2=[
"1h. Number?",
"2h. Word?",
"3h. Hour?",
"4h. Color?"
]
hard_options=[
['10', '11','21','55'],
['Book', 'Table','en','Pacino'],
['11', '21','24','18'],
['Yellow', 'Blue','Red','Green']
]
hard_answers=[
3,
4,
1,
2
]
This is my code:
import tkinter as tk
import tkinter.ttk as ttk
from questionslist import easy_questions2, easy_answers, easy_options
from openpyxl import load_workbook
from tkinter import messagebox as mb
class MainApplication(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.q_no=0
self.display_title()
self.display_question()
self.opt_selected=tk.IntVar()
self.opts=self.radio_buttons()
self.display_options()
self.buttons()
self.data_size=len(question)
self.correct=0
def display_result(self):
wrong_count = self.data_size - self.correct
correct = f"Correct: {self.correct}"
wrong = f"Wrong: {wrong_count}"
score = int(self.correct / self.data_size * 100)
result = f"Score: {score}%"
mb.showinfo("Result", f"{result}\n{correct}\n{wrong}")
def check_ans(self, q_no):
if self.opt_selected.get() == answer[q_no]:
return True
def next_button(self):
if self.check_ans(self.q_no):
self.correct += 1
self.q_no += 1
if self.q_no==self.data_size:
self.display_result()
self.submit()
self.destroy()
else:
self.display_question()
self.display_options()
def buttons(self):
next_button = tk.Button(self, text="Next",command=self.next_button, width=10)
next_button.pack(pady=50, side="bottom")
def display_options(self):
val=0
self.opt_selected.set(0)
for option in options[self.q_no]:
self.opts[val]['text']=option
val+=1
def display_question(self):
q_no = tk.Label(self, text=question[self.q_no], width=60)
q_no.pack(padx=19, pady=31, anchor="w")
def radio_buttons(self):
q_list = []
while len(q_list) < 4:
radio_button = ttk.Radiobutton(self,text=" ",variable=self.opt_selected,
value = len(q_list)+1)
q_list.append(radio_button)
radio_button.pack(padx=19, anchor="w")
return q_list
def submit(self):
wb = load_workbook('D:\\Python\\quiz\\template.xlsx')
sheet = wb.active
sheet.cell(row=1, column=2).value = "first_name"
sheet.cell(row=1, column=3).value = "correct"
sheet.cell(row=1, column=4).value = "wrong"
sheet.cell(row=2, column=3).value = self.correct
sheet.cell(row=2, column=4).value = self.data_size - self.correct
excel_filename = "D:\\Python\\quiz\\" + "data" + ".xlsx"
wb.save(excel_filename)
question = easy_questions2
options = easy_options
answer = easy_answers
if __name__ == "__main__":
root = tk.Tk()
MainApplication(root).pack(side="top", fill="both", expand=True)
root.title("Quiz")
root.geometry('800x450')
root.mainloop()
If you want to read the questions from a file (or more), you could use (suppose the file is a .txt and you've wrote a question per line):
question_list = []
with open('filename.txt', 'r+') as question_file:
lines = question_file.readlines()
# Let's move the pointer of the file back to the start to resave the questions
# as we don't want to lose them.
question_file.seek(0)
question_file.truncate()
for line in lines:
question_list.append(line) # Put each question at the end of the list.
question_file.write(line)
Use this method to retrieve all the questions and answers from all your files and to put them into lists.
Now you should have a list for the easy questions and one for the hard questions, so, to pick a random question from one list you can use a specific function from the random module, randint(a, b) which is a function that return a value in between 'a' and 'b' ('a' and 'b' included). Try it this way:
from random import randint
# You have a list of 25 hard question, let's call it hard_list
# and a list of 25 easy question, let's call it easy_list
# Now let's use our randint function to retrieve 10 random value between 0 and 24.
# As you haven't done any statement about how to choose the order of the questions,
# I'll take the first five from the hards one and the last 5 from the easy,
# but you can do it in any way you want.
# It may be a little tricky to manage the possibility of same random numbers to come out,
# surely there are better ways to do it, but this works fine.
random_questions = [] # Here I write the questions randomly chosen.
random_numbers = [] # I use this to take into account the random values.
i = 0 # Our counter.
while i < 10:
# If 5 questions have already been chosens, we change the list
# and clear the random values counter once.
if i >= 5:
if i == 5:
random_numbers.clear()
val = randint(0, 24)
if val not in random_numbers:
i += 1
random_numbers.append(val)
random_questions.append(easy_list[val])
else:
val = randint(0, 24)
if val not in random_numbers:
i += 1
random_numbers.append(val)
random_questions.append(hard_list[val])
Now, with your code, I see that the 'check_button' function doesn't check if the user have select an option or not, but maybe it's what you wanted, secondly, your button don't change the question because.. you're assigning a new Label to q_no (which, I suppose, is the number of questions answered so far)? You should assign the Label to another variable and update its text value each time the user click the button.
For example:
self.question_label = tk.Label(self, text=question[self.q_no], ....)
self.question_label.pack(...)
And when the user press the button to the next question, you check if the answer is correct, then:
self.q_no += 1
if self.q_no==(self.data_size + 1):
#
# Do what you want to do if that was the last question.
#
else:
self.question_label['text'] = question[self.q_no]
#
# Here change the value of the buttons with the answers.
#
For the third question, what format do you exactly want? There are differences between .csv, .xlsx, .xlsb, etc. But for the conversion you can use the pandas module.
These methods need a specific type of object for the conversion, so be shure to format your data in that specific way before using them:
to csv to xlsx. This is the class you can use as data structure.
From personal experience I know that you can format your datas as json to convert them to csv, but I'm not shure if it works for xlsx and other formats too.
Hope I've helped a little bit.

How to add presence check validation to an entry box in TKinter?

Firstly, I am aware that this question has already been asked. However, none of the answers for it actually answer the question.
I am creating a program that allows details to be stored in a database. These details can also be searched for using specific data (in this case, the First Name, Surname, House number and Postcode). Therefore, in order for the details to be searched for, this data needs to be present.
I have entry boxes that allow for saving data entered to a Database, but I would like it so that it won't add the details unless the aforementioned data is entered.
In pseudocode, I would like the program to function similarly to:
if Firstname or Surname or House or Postcode is not present:
output "Please enter required information"
Currently, this is my code for the entry boxes:
Label(frame1, text = "Postcode: ", font = ("arial 11"), fg = "#b83dba").grid(row = 7, column = 0, sticky = W)
pcVar = StringVar()
pc = Entry(frame1, textvariable = pcVar, bg = "silver")
pc.grid(row = 7, column = 1, sticky = W)
I would preferably like it so that, when the details required are not entered, I can use the code: messagebox.showerror("Error","Required fields are missing")
Any help would be greatly appreciated.
Never mind I just found it out so I'll post how I did it in case anyone else wants to know.
If using entryvar = Entry(frame1, textvariable = testVar) as an example, in the code for actually saving the details you would include:
Q = entryvar.get() #Returns the entry's current text as a string.
if Q == "":
messagebox.showerror("Error","Missing required fields") #Opens a messagebox informing the user that the details were not saved and that the data needs to be entered
else:
conn.execute('''INSERT INTO TABLE (DATA)
VALUES(?)''', (dataNew);
conn.commit()
messagebox.showinfo("Success","Details Saved") #Opens a messagebox informing the user that the details have saved
Apologies for my SQL as I am not very confident in that language.

Python Tkinter Gui Not Working

I have had an issue with this piece of code from awhile back, it's part of a GCSE mock and I have currently finished the working code (with text only) but I would like to expand it so that it has a nice GUI. I'm getting some issues with updating my sentence variables within the code. Anyone with any suggestions for me please do explain how I can fix it.
#GCSE TASK WITH GUI
import tkinter
from tkinter import *
from tkinter import ttk
var_sentence = ("default")
window = tkinter.Tk()
window.resizable(width=FALSE, height=FALSE)
window.title("Sentence")
window.geometry("400x300")
window.wm_iconbitmap("applicationlogo.ico")
file = open("sentencedata.txt","w")
file = open("sentencedata.txt","r")
def update_sentence():
var_sentence = sentence.get()
def submit():
file.write(sentence)
print ("")
def findword():
messagebox.showinfo("Found!")
print ("Found")
sentencetext = tkinter.Label(window, fg="purple" ,text="Enter Sentence: ")
sentence = tkinter.Entry(window)
sentencebutton = tkinter.Button(text="Submit", fg="red" , command=update_sentence)
findword = tkinter.Label(window, fg="purple" ,text="Enter Word To Find: ")
wordtofind = tkinter.Entry(window)
findwordbutton = tkinter.Button(text="Find!", fg="red" ,command=findword)
usersentence = sentence.get()
usersentence = tkinter.Label(window,text=sentence)
shape = Canvas (bg="grey", cursor="arrow", width="400", height="8")
shape2 = Canvas (bg="grey", cursor="arrow", width="400", height="8")
#Packing & Ordering Moduales
sentencetext.pack()
sentence.pack()
sentencebutton.pack()
shape.pack()
findword.pack()
wordtofind.pack()
findwordbutton.pack()
usersentence.pack()
shape2.pack()
window.mainloop()
If I understand your question right, you want to display the entered text in the usersentence label.
Changing update_sentence() function to what is shown below will archive the desired effect.
def update_sentence():
var_sentence = sentence.get()
usersentence.config(text=var_sentence)
usersentence never gets updated because you only set it once when the program starts this was the problem.

The best way to call multiple values in a function from another function in Python

As I working with the Python tkinter GUI and sqlite 3 recently to build a project, I discovered a lots of questions in Python programming. One of the questions is what would be the best way of calling multiple values in a function from another function in python? Meanwhile, I've done some research about retuning and calling value in function, and I know that in python function it can allows to return multiple value, however, when it comes to calling and I want it to call specifically the value I return e.g return (x,y,z), I really not sure how could I call it.
Here are some code that are in my project, please feel free to give me any suggestion about my code and the question that I ask above
First function
def taskUpdateB():
conn = sqlite3.connect("zzzsqlite.db")
booking = conn.cursor()
index = sOLB.curselection()
selTask = sOLB.get(index)
bookinID = selTask[-2]
getBookID = booking.execute('''SELECT bookingID FROM booking
WHERE bookingID=?''', (bookinID,))
taUp = Toplevel()
taUp.title("Task Update")
taskLabel = Label(taUp, text ="Task Update", font=('Times', 20))
taskLabel.grid(row=0)
showLabel = Label(taUp, text ="Please Select and Enter Infomation Below", font=('Times', 18))
showLabel.grid(row=1)
var = IntVar()
var = 0
fullRadio = Radiobutton(taUp, text="Fully", variable=var, value=1, command = taskUpdCom)
fullRadio.grid(row=2, sticky=W)
partRadio = Radiobutton(taUp, text="Partly", variable=var, value=2, command = taskUpdCom)
partRadio.grid(row=3, sticky=W)
notRadio = Radiobutton(taUp, text="Unable", variable=var, value=3, command = taskUpdCom)
notRadio.grid(row=4, sticky=W)
noteLabel = Label(taUp, text ="Note:", font=('Times', 16))
noteLabel.grid(row=5, sticky=W)
noteBox = Text(taUp, width=30, height =20, font=('Arial', 12,), highlightbackground='black')
noteBox.grid(row=6)
comButton = Button(taUp, text ="Task Complete and Send Invoice", command = taskUpdCom)
comButton.grid(row =7)
booking.close()
return (var, noteBox, showLabel, bookinID)
Second function
def taskUpdCom():
a = taskUpdateB
#get the data from the update list
var = taskUpdateB.var()
noteBox = taskUpdateB.noteBox()
showLabel = taskUpdateB.showLabel()
bookinID = taskUpdateB.bookinID()
selProg = str(var.get())
if selProg == 0:
showLabel["text"] = ("***Please Select Task Progress Below***")
elif noteBox.get() == "":
showLabel["text"] = ("***Please Enter Task Note Below***")
else:
conn = sqlite3.connect("zzzsqlite.db")
update = conn.cursor()
wriUpda = zzzsqliteTable.addUpdate(bookinID, selProg, noteBox)
conn.commit()
updata.close()
taskUpdateB.noteBox.delete(0, END)
tkinter.messagebox.showinfo("Notification","Your task has been updated and removed from the list")
try:
deIndex = taskUpdateB.index()#The item selected from task update delete it from the list.... will still in the database.
sOLB.delete(deIndex)
except IndexError:
pass
Please forgive my code has not been fully complete yet, and kind of messy...
Thanks for your help :)
That's not how functions work. You probably want to call the function then unpack the results in the calling scope.
var, noteBox, showLabel, bookinID = taskUpdateB()
While it is true that functions are objects in Python, they aren't stateful processors or something, they just return the result directly and then disappear (well, unless you are doing something fancy, but you aren't).

Categories

Resources