我如何在Tkinter中为多项选择题测试编写此代码



我计划在标签中显示文本,然后在底部有4个按钮,用户将选择

问题存储在一个非常原始的记事本文件中,我用冒号将每一行分开,以分隔主题、问题、正确答案,最后是3个错误答案

英语:什么是专有名词?:一个人或一个地方:一个物体:一个描述词:一个正在做的词

数学:什么是4 x 9:36:37:28:29

下面是Python代码我需要打印变量问题[1],它就是问题然后我需要有4个按钮,显示以下变量,问题[2],问题[3],问题[4],问题[5]

我不知道如何"初始化"这个,所以任何帮助都将不胜感激。我的特别困难是将变量变成"tkinter变量",尤其是当创建一个按钮时;文本";参数是可变

提前感谢

Python代码:

f1 = f.readlines()
f.close()
#Asks the user to pick a subject, in the project this
#will use your subject variable from where the user has
#chosen a subject by clicking a button
Subject = input("Pick a subject")
# Creates a blank list
questions = []
# Splits the list up by colon so we can find the subject, question,
# and correct answers. Subject = question[0], question = question[1],
# correct answer = question[2], incorrect answers = question[3] to question[5]
for question in f1:
sQuestion = question.split(":")
questions.append(sQuestion)
# Goes through the list of questions and only prints the correct subject
for question in questions:
if question[0] == Subject:
answer = input(question[1]+": "+question[2]+", "+question[3]+", "+question[4]+", "+question[5]+"?")
# Checks to see if the user guess is correct
if answer==question[2]:
print("Correct")
else:
print("Incorrect")

您的问题非常非常宽泛,不适合Stackoverflow。但是,我将尝试为您提供一些通用指南,因为我了解学习GUI编程的难度。

概述

基于事件的编程与过程代码非常不同。您不需要编写自上而下的代码,而是需要初始化UI,然后设置函数来响应事件。然后可以使用这些功能来改变显示。

我遇到的一位最有才华的程序员给了我建议,你应该从考虑你的数据结构开始。如果您已经很好地设计了数据,那么实现几乎是不言自明的。如果你有糟糕的数据结构(例如:只有一堆随机变量),这将使程序非常难以编写和理解。

使用对象提问

所以,让我们从你的问题开始。它们是一行必须解析的文本。如果所有的问题都是可以按主题存储在字典中的对象,那么编写GUI会更容易。

它不一定是花哨的,如果我们可以假设你的所有数据都是正确格式的,那么定义可能看起来像这样:

class Question():
def __init__(self, question_string):
subject, question,answer1,answer2,answer3,answer4 = question_string.split(":")
self.subject = subject
self.question = question
self.correct_answer = answer1
self.answers = (answer1, answer2, answer3, answer4)

要创建一个问题,可以从文件中传递一行。一旦你有了对象,就很容易得到主题、问题文本、正确答案和可能的答案。

>>> q = Question("English:What is a proper noun?:A person or a place:An object:A describing word:A doing word")
>>> print(q.question)
What is a proper noun?
>>> print(q.correct_answer)
A person or a place
>>> print(q.answers)
('A person or a place', 'An object', 'A describing word', 'A doing word')

这样,您就可以在文件的行上循环,为每行创建一个对象。您可以将问题存储在按主题组织的列表或词典中。既然你说你希望用户选择一个主题,那么为每个主题创建一个带有关键字的词典是最有意义的。

这可能看起来像这样:

questions = {"English": [], "Maths": []}
for row in f.readlines():
question = Question(row)
questions[question.subject].append(question)

创建GUI

一般的想法是预先创建小部件,然后在选择问题时更新小部件。为此,我们将创建一个框架来容纳一个问题,在该框架中,将有一个问题标签和四个答案单选按钮。单选按钮是正确的UI选择,因为它们代表了一种排他性的选择。还会有一个标签来显示答案是否正确。

首先,创建小部件以显示单个问题及其答案

此代码假定您以前创建过一个名为question_frameFrame。将这些小部件放在一个单独的框架中,将来可以更容易地将其他小部件添加到GUI中。

单选按钮需要共享一个tkinter变量(StringVarIntVar等)。这就是tkinter知道一次只能选择一个的方式,它提供了一种获取所选值的机制。我们将使用一个IntVar,并将其命名为answer_var

answer_var = tk.StringVar()
question_label = tk.Label(question_frame, width=80, anchor="w")
answer_radiobuttons = (
tk.Radiobutton(question_frame, anchor="w", variable=answer_var, value=0),
tk.Radiobutton(question_frame, anchor="w", variable=answer_var, value=1),
tk.Radiobutton(question_frame, anchor="w", variable=answer_var, value=2),
tk.Radiobutton(question_frame, anchor="w", variable=answer_var, value=3),
)

这创建了一个标签;正确的";或";不正确的">

result_label = tk.Label(root)

最后,我们需要在框架中排列小部件

这里使用pack是因为它简单。如果您愿意,可以使用grid

question_label.pack(side="top", fill="x", anchor="w")
result_label.pack(side="bottom", fill="x")
for button in answer_radiobuttons:
button.pack(side="top", fill="x", expand=True, anchor="w")

创建一个函数来显示问题

现在有了显示问题及其答案的小部件,现在我们有了一些问题对象,我们需要编写一个函数来显示单个问题及其答案。我们可以使用小部件的configure方法来实现这一点,该方法允许在创建小部件后对其进行修改。

在下面的示例中,答案是随机的,因此用户无法仅通过选择每个问题的第一个单选按钮来获得正确的答案。此外,我们将使用全局变量来跟踪当前问题。

def show_question(question):
global current_question
current_question = question
# configure the question label to display the question
question_label.configure(text=question.question)
# configure the radiobuttons to hold the answers
answers = list(question.answers)
random.shuffle(answers)
for i in range(4):
answer_radiobuttons[i].configure(text=answers[i])
answer_var.set(-1)  # causes buttons to show as unselected

这样,您就可以通过将问题传递给show_question来显示任何问题。例如,你可以有一个";下一个";按钮,从问题列表中选择一个问题,然后将其显示在屏幕上。

创建一个函数来检查答案

现在我们有了一个数据结构来保存问题,以及一种显示问题的方法。现在我们需要一种方法来验证结果。Radiobutton小部件接受可用于此目的的command属性;"检查答案";按钮,或者当用户试图点击";下一个问题";按钮无论如何,关键是要创建一个进行检查的函数。如何触发取决于您。

我们知道单选按钮与一个名为answer_var的变量绑定,该变量有一个返回值的get方法。我们还在列表中有单选按钮,因此我们可以使用cget方法获取所选单选按钮的文本。据此,我们可以将其与当前问题对象的正确答案进行比较。

它看起来像这样:

def check_answer():
choice = answer_var.get()
answer = answer_radiobuttons[choice].cget("text")
if answer == current_question.correct_answer:
result_label.configure(text="Correct")
else:
result_label.configure(text="Incorrect")

作为如何使用此函数的示例,我们可以要求单选按钮在配置时调用此函数。我们可以通过更改单选按钮的创建方式,添加command属性:来实现这一点

answer_radiobuttons = (
tk.Radiobutton(main_frame, anchor="w", variable=answer_var, value=0, command=check_answer),
tk.Radiobutton(main_frame, anchor="w", variable=answer_var, value=1, command=check_answer),
tk.Radiobutton(main_frame, anchor="w", variable=answer_var, value=2, command=check_answer),
tk.Radiobutton(main_frame, anchor="w", variable=answer_var, value=3, command=check_answer),
)

摘要

我遗漏了很多细节,但那是因为没有最好的方法来做到这一点,而且你的问题非常宽泛。然而,通用模式适用于大多数GUI程序:

  • 初始化数据
  • 初始化显示器
  • 通过对用户的操作作出反应来更新显示

最新更新