因此,我已经从事一段时间的测验应用程序(大约4天)。我设法制作了代码的所有逻辑部分(测验,测验问题处理,分数输出等)。我知道这段代码既不是最好也不是最有效的,但我只是初学者。无论如何,tkinter的入口函数的get()函数不会返回任何内容。我知道有一种解决方法,但是我不确定如何使用外部循环来实现该解决方案。请帮我。这是我的代码:
import random
from time import sleep
import tkinter as tk
from tkinter import *
import threading
class App(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.start()
def callback(self):
self.root.quit()
def run(self):
self.root = tk.Tk()
self.root.protocol("WM_DELETE_WINDOW", self.callback)
#label = tk.Label(self.root, text="Hello World")
#label.pack()
#Button(self.root, text = "Choose", command=btnPressed).pack()
tk.Label(self.root, text="Answer: ").grid(row=0,column=0)
#answerField_get = StringVar()
answerField = tk.Entry(self.root)
answerField.grid(row=0, column=1)
#Button(self.root, text='Show').grid(row=3, column=1, sticky=tk.W, pady=4)
print(str(answerField.get()))
Button(self.root, text='Show', command = lambda arg1=answerField.get():btnPressed("<"+str(arg1)+">")).grid(row=3, column=1, sticky=tk.W, pady=4)
self.root.mainloop()
def sendTMP(self, sendStr):
btnPressed(sendStr)
SCORE_SET = []
qasTmp = {}
qas = {}
qasSequenced = {}
incorrectResponses = []
incorrectResponses_replies = []
quiztaker_name = ""
attachAnsCode = "%% Fun fact: rgb computer parts lovers are somewhat weird hehe %%********^^&&^^&&^^&&"
qasQsSequenced = False
qasQsL = 0
qasQsL_divisionFactor = 2
qasINDEX = 0
err_noCode = "<!>NO_CODE<!>"
codes_answerCorrect = "A_C"
codes_answerIncorrect = "A_I"
answerCode = err_noCode
score = 0
randQs = False
# File
# the metadata will corrupt the reading from the file, a separate file, created in the targeted system, must be used to properly read the data.
# comment out the file name that is not being used.
filename_windows = "qas-windows"
filename_rpi = "qas-rpi"
filename = filename_windows
fileformat = "txt"
file_name_format = filename + "." + fileformat
spaceIndicator = "|"
char_commentLine_qasFile = "*"
char_newline = "`"
print("Information about modes: ")
print(" *Easy: No point deductions for an incorrect response")
print(" *Hard: One point deducted for every incorrect response")
modes_err = "0"
modes_ez = "1"
modes_hard = "2"
gameOn = False
selectedMode = modes_err
askReplay = True
data_prev = []
with open("SCORES.txt", 'r') as scores_prev:
data_prev = scores_prev.readlines()
scores_prev.close()
for i in range(0, len(data_prev)):
SCORE_SET.append(data_prev[i])
def btnPressInform():
print("A button has been pressed!")
def importAndClean():
# import questions from qas-windows.txt
with open(file_name_format, 'r') as document:
for line in document:
if line.strip():
key, value = line.split(None, 1)
if key[0] != char_commentLine_qasFile: # Custom comments for the txt file
qasTmp[key] = value.split()
# Clean up dictionary input from the txt file
for i in range(0, len(qasTmp)): # FIVE FOR LOOPS!!!! (FOUR IN THIS ONE)
for ii in qasTmp:
output = ""
output_ans = ""
for iii in range(0, len(ii)):
if ii[iii] != spaceIndicator:
output += ii[iii]
else:
output += " "
for iiii in range(0, len(qasTmp[ii])):
TEMP = str(qasTmp[ii])
for iiiii in range(2, len(TEMP) - 2): # IGNORE [' and ']
# print(TEMP[iiiii])
if TEMP[iiiii] != spaceIndicator:
output_ans += TEMP[iiiii]
else:
output_ans += " "
# print(output + " : " + output_ans) #Output question: answer
qas[output] = output_ans
importAndClean()
def getL():
qasQsL = len(qas) / qasQsL_divisionFactor # only ask 1/qasQsL_divisionFactor the questions
qasQsL = int(qasQsL) # round to an integer as odd numbers will end in .5 after division
if qasQsL < 1:
qasQsL = 1 # Have atleast ONE question
return qasQsL
def debug1(keys, vals, index, i):
print(str(index) + "/" + str((len(keys) - 1)))
print(keys)
print(vals)
print()
print(keys[index] + " : " + vals[index] + "\n")
print("Sorting original index " + str(i) + " at random index " + str(index))
def debug2(keys, vals, index):
print(keys)
print(vals)
print("\n")
def debugFinal():
print("Temp (OG reading): ")
print(qasTmp)
print("\nQAS (Non-sequenced, cleaned): ")
print(qas)
print("\nQAS Sequenced (Randomly sequenced, cleaned): ")
print(qasSequenced)
def randomize(qasQsL_tmp):
qas_keys = list(qas.keys())
qas_vals = list(qas.values())
if randQs == False:
qasQsL_tmp = len(qas_keys) # all questions
print("You will be asked all " + str(qasQsL_tmp) + " questions")
else:
qasQsL_tmp = getL() # random question
print("You will be asked " + str(qasQsL_tmp) + " questions out of " + str(len(qas)) + " possible questions!")
print("\n\nRandomly sequencing questions...")
for i in range(0, qasQsL_tmp):
INDEX = random.randint(0, qasQsL_tmp - 1)
# debug1(qas_keys, qas_vals, INDEX, i)
qasSequenced[qas_keys[INDEX]] = qas_vals[INDEX]
qas_keys.pop(INDEX)
qas_vals.pop(INDEX)
qasQsL_tmp -= 1
# debug2(qas_keys, qas_vals, INDEX)
sleep(0.05)
# debugFinal()
print("Done sequencing! Starting quiz now! \n\n")
return "0"
def quizController(index):
qas_keys = list(qasSequenced.keys())
qas_vals = list(qasSequenced.values())
# print(qas_keys)
# print(qas_vals)
lines = []
lines_index = 0
tmp = ""
# Splitter
for i in range(0, len(qas_keys[index])):
if lines_index < len(qas_keys[index]) - 1:
if qas_keys[index][i] != char_newline:
tmp += qas_keys[index][i]
else:
lines.append(tmp)
tmp = ""
lines.append(tmp)
# Multiple choice
mChoiceQ = False
mChoice_startBrackets = 0
mChoice_endBrackets = 0
mChoice_options = []
mChoice_numOptions = 0
mChoice_seperatorsAt = []
for i in range(0, len(qas_keys[index])):
if qas_keys[index][i] == "[":
mChoice_startBrackets = i
mChoiceQ = True
elif qas_keys[index][i] == "]":
mChoice_endBrackets = i
elif qas_keys[index][i] == "/":
mChoice_seperatorsAt.append(i)
if mChoiceQ == True:
TEMP = ""
for i in range(mChoice_startBrackets, mChoice_endBrackets + 1):
if qas_keys[index][i] != "[":
if qas_keys[index][i] != "/" and qas_keys[index][i] != "]":
TEMP += qas_keys[index][i]
else:
mChoice_options.append(TEMP)
TEMP = ""
mChoice_numOptions = len(mChoice_seperatorsAt) + 1
# Default options (yes, no) full names
for i in range(0, len(mChoice_options)):
if mChoice_options[i].lower() == "y":
mChoice_options.append("yes")
elif mChoice_options[i].lower() == "n":
mChoice_options.append("no")
# if mChoiceQ == True:
# print("It is a multiple choice question! There are " + str(mChoice_numOptions) + " options. They are: ")
# print(mChoice_options)
print("\nQuestion " + str(index + 1) + "/" + str(qasQsL) + ":")
for i in range(0, len(lines)):
print(lines[i])
# answer = ""
answer = input(">")
# answer = input(qas_keys[index]+ ": ")
if mChoiceQ == False:
if len(answer) > 0:
if answer.lower() == str(qas_vals[index]).lower():
return codes_answerCorrect
else:
incorrectResponses.append(qas_keys[index])
incorrectResponses_replies.append(answer)
# print("DEBUG: Incorrect response! Expected '" + str(qas_vals[index]).lower() + "', received " + answer.lower())
return codes_answerIncorrect
else:
print("Please insert an answer!")
else:
allowedResponse = False
for i in range(0, len(mChoice_options)):
if answer.lower() == mChoice_options[i].lower():
allowedResponse = True
if allowedResponse == True:
ans = qas_vals[index].lower()
yn = False
ans_yesno = ""
if ans.lower() == "y" or ans.lower() == "n":
yn = True
else:
yn = False
if yn == True:
if ans == "y":
ans_yesno = "yes"
elif ans == "n":
ans_yesno = "no"
if len(answer) > 0:
if yn == True:
if answer.lower() == ans.lower() or answer.lower() == ans_yesno.lower():
return codes_answerCorrect
else:
return codes_answerIncorrect
incorrectResponses.append(qas_keys[index])
incorrectResponses_replies.append(answer)
else:
if answer.lower() == ans.lower():
return codes_answerCorrect
else:
return codes_answerIncorrect
incorrectResponses.append(qas_keys[index])
incorrectResponses_replies.append(answer)
else:
print("Please insert an answer!")
else:
print("Invalid response! You may only enter the following: " + str(mChoice_options))
def saveScore():
# Clear file!
score_file_CLEAR = open("SCORES.txt", "wt")
score_file_CLEAR.close()
# Save contents
score_file = open("SCORES.txt", "wt")
for i in range(0, len(SCORE_SET)):
score_file.write(SCORE_SET[i])
print("Done saving!")
def btnPressed(tmp):
print(tmp)
app = App()
while True:
qasQsL = len(qasSequenced)
if gameOn == True and selectedMode != modes_err:
if qasQsSequenced == True:
if qasINDEX < qasQsL:
answerCode = quizController(qasINDEX)
else:
output = randomize(qasQsL)
if output == "0":
qasQsSequenced = True
if qasINDEX < qasQsL:
if answerCode == codes_answerCorrect:
score += 1
qasINDEX += 1
# print("DEBUG: Correct! Score set to: " + str(score))
elif answerCode == codes_answerIncorrect:
if selectedMode == modes_hard:
score -= 1
qasINDEX += 1
# print("Score set to: " + str(score))
else:
print("")
if qasQsL != 0:
score_per = score / qasQsL
if score_per < 0:
score_per = 0
if score < 0:
score = 0
print("You score was lower than 0, therefore it was set to 0")
# print("Your score: " + str(score) + "/" + str(len(qasSequenced)) + " (" + str(int(score_per*100)) + "%)")
# if score != qasQsL:
# print("You responded to the following questions incorrectly:")
# print(incorrectResponses)
if score / qasQsL == 1:
SCORE_SET.append(quiztaker_name + " scored " + str(score) + " out of " + str(qasQsL) + "(" + str(
int(score / qasQsL) * 100) + "%). PART OF Qs: " + str(
int(randQs)) + " at division factor 1/" + str(qasQsL_divisionFactor) + ", MODE: " + str(
int(selectedMode)) + "\n")
if score / qasQsL != 1:
SCORE_SET.append(quiztaker_name + " scored " + str(score) + " out of " + str(qasQsL) + " (" + str(
int(score / qasQsL) * 100) + "%). PART OF Qs: " + str(
int(randQs)) + " at division factor 1/" + str(qasQsL_divisionFactor) + ", MODE: " + str(
int(selectedMode)) + " They got the following questions wrong: \n")
for i in range(0, len(incorrectResponses)):
SCORE_SET.append(" " + str(i + 1) + ") " + incorrectResponses[i] + " --RESPONSE-- " +
incorrectResponses_replies[i] + "\n")
SCORE_SET.append("\n")
saveScore()
qasQsSequenced = False
gameOn = False
print("\nGame over!")
askReplay = True
else:
continue
elif askReplay == False:
TEMP = input("What mode would you like? (E = Easy, H = Hard): ")
if len(str(TEMP)) > 0:
if str(TEMP).lower() == "e":
selectedMode = modes_ez
gameOn = True
print("Set mode to: NO POINT DEDUCTIONS")
elif str(TEMP).lower() == "h":
selectedMode = modes_hard
gameOn = True
print("Set mode to: POINT DEDUCTIONS ALLOWED")
else:
print("Error: Undefined response. Please try again!")
elif askReplay == True:
TEMP = input("Would you like to (re)do the quiz? (Y/N): ")
if len(str(TEMP)) > 0:
if str(TEMP).lower() == "y":
askReplay = False
qasQsSequenced = False
qasQsL = 0
qas.clear()
qasSequenced.clear()
qasTmp.clear()
qasINDEX = 0
incorrectResponses.clear()
answerCode = err_noCode
score = 0
selectedMode = modes_err
importAndClean()
randQs = False
USER_TEMP = input("Please enter your name >")
if len(USER_TEMP) > 0:
quiztaker_name = str(USER_TEMP)
print("Welcome " + quiztaker_name + "!")
USER_TEMP = input("Would you like all questions (a) or a part of the questions(p)? (A/P) > ")
if len(USER_TEMP) > 0:
if USER_TEMP.lower() == "a":
print("Set to all questions!")
randQs = False
elif USER_TEMP.lower() == "p":
print("Set to 1/" + str(qasQsL_divisionFactor) + " questions (pre-set variable)")
randQs = True
else:
print("Undefined response! Setting to default value (ALL)")
randQs = False
gameOn = False
askReplay = False
elif str(TEMP).lower() == "n":
selectedMode = modes_hard
gameOn = False
print("Exiting now!")
saveScore()
sleep(2)
exit(0)
else:
print("Error: Undefined response. Please try again!")
Entry()
与input()
不同。它不等待数据,仅通知tkitner
您要显示Entry
小部件(mainloop()
将显示它),Python
转到下一行代码,并且在运行print(str(answerField.get()))
之前它甚至显示窗口-因此您尝试从空Entry
中获取。
您应该在分配给Button
的功能中获取它,在Entry
中输入一些文字后将按此功能。
同样的问题是
lambda arg1=self.answerField.get():print(arg1)
在开始时定义了args
时,仅从Entry
分配一次lambda
值-因此它将获得空字符串。您应该在函数内部使用它
command=lambda:print(self.answerField.get())
或创建常规功能并分配给按钮。
最小工作代码
import tkinter as tk
import threading
class App(threading.Thread):
def run(self):
self.root = tk.Tk()
#self.root.protocol("WM_DELETE_WINDOW", self.on_close)
self.answerField = tk.Entry(self.root)
self.answerField.grid(row=0, column=1)
#b = tk.Button(self.root, text='Show', command=lambda:print(self.answerField.get()))
b = tk.Button(self.root, text='Show', command=self.on_click)
b.grid(row=1, column=1)
self.root.mainloop()
def on_click(self):
print(self.answerField.get())
#def on_close(self):
# self.root.destroy()
App().start()
#App().run()