如何使用文本文件中的单选按钮

时间:2017-04-01 16:35:46

标签: python python-3.x tkinter radio-button

我正在使用tkinter

在python 3中创建一个简单的多项选择测验

我打算在文本文件中添加所有问题和答案。但我不知道如何让我的单选按钮与文本文件一起使用然后调用它们。我需要一个小例子,所以我可以完成我的程序。 我试图使用谷歌和其他python文件,但我没有得到任何正确的。

import sys
from tkinter import *

root=Tk()
name=StringVar(value='Enter Name Here')
cn=StringVar(value='Enter CN Here')

def random():
    mlabel=Label(root,text="U CLicked Me").pack()
    return

def random1():
    mtext=name.get()
    mno=cn.get()
    mlabel2=Label(root,text=mtext).pack()
    mlabel3=Label(root,text=mno).pack()

def mquit():
    mexit=messagebox.askyesno(title="Quit",message="Quit The Test ?")
    if mexit > 0:
        root.destroy()
        return

root.geometry('700x700+400+400')
root.title('Welcome To Quiz')

mainmenu=Menu(root)

root.configure(menu=mainmenu)

submenu=Menu(mainmenu,tearoff=0)
mainmenu.add_cascade(label="Options",menu=submenu)
submenu.add_command(label="Restart",command=random)
submenu.add_command(label="Close",command=mquit)

mentry=Entry(root,textvariable=name).pack()
mentry=Entry(root,textvariable=cn).pack()
mbutton=Button(root,text='Ok',command=random1,fg='red',bg='blue').pack()

root.mainloop()

3 个答案:

答案 0 :(得分:1)

您需要了解两个部分。

第一部分是从文本文件中获取值。如何执行此操作取决于文本文件的格式(您尚未指定)。我建议你使用csv(csv documentation)甚至配置文件(config parser documentation)。

将问题和答案加载到变量后,您可以将值分配给radiobuttons。 要记住的关键点是组中的单选按钮都指向一个变量。如果以编程方式将变量设置为有效选项,则将选择该按钮;如果用户选择了radiobutton,则变量将设置为该值 - 您可以根据从csv或配置文件加载的答案测试该值。

(来自Rocci Rossi的繁忙Python开发者的Modern TKinter):

使用ttk.Radiobutton函数创建Radiobutton,通常作为一组:

phone = StringVar()
home = ttk.Radiobutton(parent, text='Home', variable=phone, value='home')
office = ttk.Radiobutton(parent, text='Office', variable=phone, value='office')
cell = ttk.Radiobutton(parent, text='Mobile', variable=phone, value='cell')

该组中的每个单选按钮将具有相同的链接变量,但具有不同的值;当变量具有给定值时,将选择单选按钮,否则将取消选择。当链接变量不存在时,radiobuttons也会显示" tristate"或者不确定,可以检查 通过"替代"州旗。

答案 1 :(得分:0)

为了向您展示如何完成,下面是一个完整的,独立的tkinter应用程序,它说明了基础知识(以及一个或两个奖励功能)。

需要掌握的一个重点是,作为一个整体,所有tk.Radiobutton一起构成一个功能组,并共享一个tk.IntVar控制变量来保存其中一个值(如果有的话),目前正在按下。当按下组中的一个时,使用它不仅会更新该按钮的指示符,还会更新所有其他指示符的指示符。自动 - 这样就无需编写任何自己的代码来实现这一目标。有关tkinter"变量"的更多信息,请参阅this article。类。

问题和答案信息是从纯文本文件中读取的,该文件以超简单格式构成,每行只有一个数据。第一行是问题。第二行是可能答案的数量。第三行是正确答案的编号(从1开始计算)。在这三个之后是可变数量的行,每行包含指定数量的答案之一。任何这些行都允许使用可选注释。

这是一个显示问答文件中数据布局的示例:

Question #1
4  // answer count
2  // number of correct answer
q1 answer1
q1 answer2
q1 answer3
q1 answer4
Question #2
3  // answer count
3  // number of correct answer
q2 answer1
q2 answer2
q2 answer3
Question #3
2  // answer count
1  // number of correct answer
q3 answer1
q3 answer2

这是运行脚本中的结果:

[screenshot of app running

这是代码:

try:
    import Tkinter as tk
    import tkFont
    import tkMessageBox
except ImportError:  # Python 3
    import tkinter as tk
    import tkinter.font as tkFont
    from tkinter import messagebox as tkMessageBox

class Struct(object):
    """Generic container object."""
    def __init__(self, **kwds):  # keyword args define attribute names and their values
        self.__dict__.update(**kwds)

class App(tk.Frame):
    MIN_WIDTH = 40  # characters
    COMMENT_PREFIX = '//'

    def __init__(self, filename, master=None):
        tk.Frame.__init__(self, master)
        self.grid()
        self.qa_info = self.read_qa_file(filename)
        self.current_question = 0  # index of Struct in qa_info
        self.create_widgets()

    def qa_readline(self, file):
        """Read a single line from file, remove any comment and trailing newline."""
        line = file.readline().rstrip()
        if line:
            try:
                line = line[:line.index(self.COMMENT_PREFIX)]
            except ValueError:
                pass
        return line

    def read_qa_file(self, filename):
        qa_info = []
        with open(filename, 'rt') as file:
            while True:
                question = self.qa_readline(file)
                if not question:  # end-of-file?
                    break
                num_answers = int(self.qa_readline(file))
                correct_answer_num = int(self.qa_readline(file))-1
                answers = [self.qa_readline(file) for _ in range(num_answers)]
                qa_info.append(Struct(question=question, num_answers=num_answers,
                                      correct_answer_num=correct_answer_num,
                                      answers=answers))
        return qa_info

    def create_widgets(self):
        self.btn_font = tkFont.Font(family="Helvetica", size=10, weight='normal')
        self.query_font = tkFont.Font(family="Helvetica", size=12, weight='normal')
        self.ans_font = tkFont.Font(family="Helvetica", size=10, weight='normal')

        self.next_btn = tk.Button(self, text='Next question', font=self.btn_font,
                                  anchor=tk.NW, justify=tk.LEFT,
                                  command=self.next_question)
        self.next_btn.grid(column=0, row=0)
        self.create_query_frame(self.current_question)

    def create_query_frame(self, question_num):
        """Create independent Frame holding question Label and answer Radiobuttons."""
        try:
            getattr(self, 'qa_frame').destroy()  # remove any previous question
        except AttributeError:
            pass
        qa_frame = self.qa_frame = tk.Frame(self)
        qa_frame.grid(column=0, row=1)

        question = self.qa_info[question_num].question
        self.question = tk.Label(qa_frame, text=question, font=self.query_font,
                                 width=self.MIN_WIDTH, anchor=tk.NW)
        question_row = 0  # relative to query frame
        self.question.grid(column=0, row=question_row)

        self.ans_var = tk.IntVar()  # Note: shared by all answer Radiobuttons
        self.ans_var.set(-1)  # set to something that won't match any Radiobutton's value

        # create answer buttons
        answers = self.qa_info[question_num].answers
        self.answer_buttons = []
        first_answer_row = question_row+1  # relative to query frame
        for i, answer in enumerate(answers):
            radiobutton = tk.Radiobutton(qa_frame, text=answer, font=self.query_font,
                                         width=self.MIN_WIDTH, anchor=tk.NW, value=i,
                                         variable=self.ans_var, relief=tk.RIDGE,
                                         command=lambda btn=i: self.button_pressed(btn))
            radiobutton.grid(column=0, row=first_answer_row+i)
            self.answer_buttons.append(radiobutton)

    def next_question(self):
        """Determine index of next question and create frame holding it."""
        self.current_question += 1
        if self.current_question > len(self.qa_info)-1:  # last question?
            self.current_question = 0  # wrap-around
        self.create_query_frame(self.current_question)

    def button_pressed(self, button):
        """React to answer Radiobutton presses.
           (Could also keep score here...)
        """
        qa_info = self.qa_info[self.current_question]
        if button == qa_info.correct_answer_num:
            tkMessageBox.showinfo('Feedback', "That's absolutely correct!")
        else:
            tkMessageBox.showerror('Feedback', "Sorry, that's not right")
            self.ans_var.set(-1)  # turn indicator off

qa_filename = 'questions_and_answers.txt'
app = App(qa_filename)
app.master.title('Q & A Demo')
app.mainloop()

答案 2 :(得分:0)

这是我使用tkinker找到它的方法

Picker = StringVar(value=()) #This sets the variable to all option within the radiobuttons 
Option1 = Radiobutton(root, text="Option1", Variable=Picked, value="Option1")
Option2 = Radiobutton(root, text="Option2", Variable=Picked, value="Option2")

text_file = open(Output.text", "w+")
text_file.write(Picked.get())