Закройте окно Tkinter с помощью кнопки, только если все переменные были установлены

#python #python-2.7 #button #user-interface #tkinter

#python #python-2.7 #кнопка #пользовательский интерфейс #tkinter

Вопрос:

Я пытаюсь создать Tkinter-версию вопросника, где каждый вопрос имеет множественный выбор (с использованием переключателей). Я хочу иметь возможность закрыть окно только в том случае, если были даны ответы на все вопросы. Есть ли способ сделать это? Ничто из того, что я нашел на сайте, не касалось условных кнопок. В настоящее время моя кнопка закрывает окно независимо от того, что и мой код выглядит следующим образом:

 import Tkinter
import ttk


class Questionnaire(Tkinter.Frame):
    def __init__(self, parent):
        Tkinter.Frame.__init__(self, parent)
        self.parent = parent

        self.canvas = Tkinter.Canvas(root, borderwidth=0, background="#ffffff")
        self.frame = Tkinter.Frame(self.canvas, background="#ffffff")
        self.vsb = Tkinter.Scrollbar(root, orient="vertical", command=self.canvas.yview)
        self.canvas.configure(yscrollcommand=self.vsb.set)

        self.vsb.pack(side="right", fill="y")
        self.vsb.bind_all("<MouseWheel>", self._on_mousewheel)
        self.canvas.pack(side="left", fill="both", expand=True)
        self.canvas.create_window((4, 4), window=self.frame, anchor="nw", 
                                  tags="self.frame")

        self.frame.bind("<Configure>", self.OnFrameConfigure)
        self.initUI()

    def OnFrameConfigure(self, event):
        '''Reset the scroll region to encompass the inner frame'''
        self.canvas.configure(scrollregion=self.canvas.bbox("all"))

    def _on_mousewheel(self, event):
        self.canvas.yview_scroll(-1 * event.delta, "units")

    def initUI(self):
        """ question and instructions are just lists of strings """
        all_questions = [[] for _ in range(len(question))]
        answers = [[] for _ in range(len(question))]
        button_1 = [[] for _ in range(len(question))]
        button_2 = [[] for _ in range(len(question))]
        button_3 = [[] for _ in range(len(question))]
        button_4 = [[] for _ in range(len(question))]
        Instructs = [[] for _ in range(len(instructions))]
        self.parent.title("Questionnaire")
        self.style = ttk.Style()
        self.style.theme_use("default")

        self.pack(fill=Tkinter.BOTH, expand=1)
        r = 0
        for i in range(len(instructions)):
            Instructs[i] = Tkinter.Label(self.frame, text=instructions[i]).grid(row=r, column=1)
            r  = 1

        for i in range(len(all_questions)):
            all_questions[i] = Tkinter.Label(self.frame, text=question[i])
            all_questions[i].grid(row=r, column=1, columnspan=8)

            answers[i] = Tkinter.IntVar()
            button_1[i] = Tkinter.Radiobutton(self.frame, text="1", variable=answers[i], value=1)
            button_1[i].grid(row=r, column=9)
            button_2[i] = Tkinter.Radiobutton(self.frame, text="2", variable=answers[i], value=2)
            button_2[i].grid(row=r, column=10)
            button_3[i] = Tkinter.Radiobutton(self.frame, text="3", variable=answers[i], value=3)
            button_3[i].grid(row=r, column=11)
            button_4[i] = Tkinter.Radiobutton(self.frame, text="4", variable=answers[i], value=4)
            button_4[i].grid(row=r, column=12)
            r  = 1

        Submit = Tkinter.Button(self.frame, text="Submit", command=self.close_window)
        Submit.grid(row=r, column=11, columnspan=2)

        self.mainloop()
        self.answers = [ans.get() for ans in answers]

    def close_window(self):
        self.parent.destroy()


root=Tkinter.Tk()
app = Questionnaire(root)
root.mainloop()
  

Комментарии:

1. вы пробовали добавить какой-нибудь условный код в свой close_window метод?

2. Да, я передал ответы и получил «если 0 не в [ans.get() для ans в ответах]: self.parent.destroy(), но это не сработало (я полагаю, потому что условие должно быть вычислено перед переменными?).

Ответ №1:

Вам нужно внести два изменения:

  1. Везде используйте self.answers вместо answers
  2. Удалить self.mainloop() из initUI метода

Работающий код:

 import Tkinter
import ttk


class Questionnaire(Tkinter.Frame):
    def __init__(self, parent):
        Tkinter.Frame.__init__(self, parent)
        self.parent = parent

        self.canvas = Tkinter.Canvas(root, borderwidth=0, background="#ffffff")
        self.frame = Tkinter.Frame(self.canvas, background="#ffffff")
        self.vsb = Tkinter.Scrollbar(root, orient="vertical", command=self.canvas.yview)
        self.canvas.configure(yscrollcommand=self.vsb.set)

        self.vsb.pack(side="right", fill="y")
        self.vsb.bind_all("<MouseWheel>", self._on_mousewheel)
        self.canvas.pack(side="left", fill="both", expand=True)
        self.canvas.create_window((4, 4), window=self.frame, anchor="nw",
                                  tags="self.frame")

        self.frame.bind("<Configure>", self.OnFrameConfigure)
        self.initUI()

    def OnFrameConfigure(self, event):
        '''Reset the scroll region to encompass the inner frame'''
        self.canvas.configure(scrollregion=self.canvas.bbox("all"))

    def _on_mousewheel(self, event):
        self.canvas.yview_scroll(-1 * event.delta, "units")

    def initUI(self):
        question=['q1','q2','q3','q4']
        instructions=['i1','i2','i3','i4']
        all_questions = [[] for _ in range(len(question))]
        self.answers = [[] for _ in range(len(question))]
        button_1 = [[] for _ in range(len(question))]
        button_2 = [[] for _ in range(len(question))]
        button_3 = [[] for _ in range(len(question))]
        button_4 = [[] for _ in range(len(question))]
        Instructs = [[] for _ in range(len(instructions))]
        self.parent.title("Questionnaire")
        self.style = ttk.Style()
        self.style.theme_use("default")

        self.pack(fill=Tkinter.BOTH, expand=1)

        r = 0
        for i in range(len(instructions)):
            Instructs[i] = Tkinter.Label(self.frame, text=instructions[i]).grid(row=r, column=1)
            r  = 1

        for i in range(len(all_questions)):
            all_questions[i] = Tkinter.Label(self.frame, text=question[i])
            all_questions[i].grid(row=r, column=1, columnspan=8)

            self.answers[i] = Tkinter.IntVar()
            button_1[i] = Tkinter.Radiobutton(self.frame, text="1", variable=self.answers[i], value=1)
            button_1[i].grid(row=r, column=9)
            button_2[i] = Tkinter.Radiobutton(self.frame, text="2", variable=self.answers[i], value=2)
            button_2[i].grid(row=r, column=10)
            button_3[i] = Tkinter.Radiobutton(self.frame, text="3", variable=self.answers[i], value=3)
            button_3[i].grid(row=r, column=11)
            button_4[i] = Tkinter.Radiobutton(self.frame, text="4", variable=self.answers[i], value=4)
            button_4[i].grid(row=r, column=12)
            r  = 1

        Submit = Tkinter.Button(self.frame, text="Submit", command=self.close_window)
        Submit.grid(row=r, column=11, columnspan=2)


    def close_window(self):
        if 0 not in [ans.get() for ans in self.answers]: self.parent.destroy()


root=Tkinter.Tk()
app = Questionnaire(root)
root.mainloop()