Tkinter按钮:在运行脚本的主要部分之前,如何确保按下某些按钮

时间:2016-01-30 23:19:47

标签: python python-3.x button tkinter

我为这个措辞严厉的问题道歉,我无法想出一个更好的方式来表达我的问题。我正在编写一个脚本,使用交互式GUI演示Monty Hall问题。在我的第一帧上,我有3个标有“门A”,“门B”和“门C”的按钮。在这3个按钮下面,我还有另外两个标有“Switch Choice”和“Keep Choice”的按钮。

代表“门”的3个按钮调用名为initialGuess(self,door)的方法,而表示用户是否想要保留或切换其选择的底部2个按钮调用方法switch_choice(self, val)。我想确保用户选择一扇门,以及他是否想在模拟蒙蒂霍尔问题之前切换他的选择。这两个按钮都运行两种不同的方法,如何编写一个脚本以确保两个方法都已运行,一旦确认用户做出了两个选择,它将运行模拟的主要部分。

这里有帮助,我的按钮和相应的方法。 (我事先为我计划为他们创建其他方法的所有全局变量道歉,这只是一个开始的蓝图。)

class MontyHallSim(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller

        label = Label(self, text="Monty Hall Problem", font=Large_Font)
        label.place(x=150, y=100, width=500, height=50)

        doorA = Button(self, text="Door A", font=Small_Font,
                       relief=RAISED, height=10, width=50,
                       command=lambda: self.initialGuess("A"))
        doorA.place(x=125, y=200, width=150, height=400)

        doorB = Button(self, text="Door B", font=Small_Font,
                       relief=RAISED, height=10, width=50,
                       command=lambda: self.initialGuess("B"))
        doorB.place(x=325, y=200, width=150, height=400)

        doorC = Button(self, text="Door C", font=Small_Font,
                       relief=RAISED , height=10, width=50,
                       command=lambda: self.initialGuess("C"))
        doorC.place(x=525, y=200, width=150, height=400)

        switch= Button(self, text="Switch Choice",
                       relief=RAISED, height=10, width=50,
                       command=lambda: self.switch_choice("Y"))
        switch.place(x=100, y=600, width=100, height=50)

        no_switch = Button(self, text="Keep Choice",
                           relief=RAISED,  height=10, width=50,
                           command=lambda: self.switch_choice("N"))
        no_switch.place(x=600, y=600, width=100, height=50)

    global doors
    global game
    global prize
    global guess
    global empty_door
    global initial
    global moderator
    global stay
    global switch
    global selection

    selection=None
    moderator="Moderator"
    guess=None
    empty_door="Empty"
    prize="Prize"
    initial="Guess"
    doors=("A", "B", "C")
    game={"A":"Empty","B":"Empty", "C":"Empty"}

    def initialGuess(self,door):
        guess=door
        game[guess]=initial
        tm.showinfo("Monty Hall", "You Chose Door %.2s" %guess)
        return guess

    def switch_choice(self,val):
        switch="Y"
        stay="N"
        if val==switch:
            selection=switch
            tm.showinfo("Monty Hall", "You Chose To Switch Your Guess!")
        else:
            selection=stay
            tm.showinfo("Monty Hall", "You Chose The Original Door")
        return selection

    def run_sim(self):
        iterations=1000
        win_count=0
        lose_count=0
        for _ in range(iterations):
            #Sets the Prize stores Prize "Key" in a value for later use
            placed=random.choice(doors)
            game[placed]=prize
            prize_key=list(game.keys())[list(game.values()).index(prize)]

            #Sets Moderators Choice
            moder=list(game.keys())[list(game.values()).index(empty_door)]
            game[moder]=moderator

            #checks to see if switch is performed
            if selection=="Y":
                new_guess=random.choice(
                    [x for x in doors if x != guess and x!=moderator])
                game[new_guess]=initial
                game[guess]=empty_door
                guess=new_guess
                game[prize_key]=prize
            else:
                pass

            #Checks Game dictionary for "Guess"; If guess is present you
            #lose...
            #If guess is NOT present that means the Prize is in the door that
            #you guessed
            try:
                open_guess = (
                    list(game.keys())[list(game.values()).index(guess)])
                if open_guess in game:
                    lose_count += 1
            except ValueError:
                win_count += 1

        percent_won=float(win_count/iterations*100.)
        percent_lost=float(lose_count/iterations*100)
        tm.showinfo("Percent Won: %.2f" %percent_won)
        tm.showinfo("Percent Lost: %.2f" %percent_lost)

1 个答案:

答案 0 :(得分:0)

您可以停用(tk.DISABLED)并启用(tk.NORMAL)按钮和其他小部件。因此,可以禁用keep choice按钮,直到做出选择。您可能想要使用Radiobutton吗?也许messagebox来检查玩家是否想要切换?

这是一个快速而混乱的代码示例,它可能会给你一些想法。

import tkinter as tk
from tkinter import ttk, messagebox

def reset_choice():
    button_run.configure(state=tk.DISABLED)
    button_a.configure(state=tk.NORMAL)
    button_b.configure(state=tk.NORMAL)
    button_c.configure(state=tk.NORMAL)

def reset_sim():
    global choice
    global switch
    reset_choice()
    choice.set('')
    switch = False

def run_sim():
    global choice
    global switch
    if messagebox.askyesno('Are you sure?', 'You chose {}, do you want to switch?'.format(choice.get())):
        reset_choice()
        switch = True
    else:
        print('You chose door {}'.format(choice.get()))
        if switch:
            print('You switched choice before running')
        print('Running sim...')
        reset_sim()


def select_door():
    button_run.configure(state=tk.NORMAL)
    button_a.configure(state=tk.DISABLED)
    button_b.configure(state=tk.DISABLED)
    button_c.configure(state=tk.DISABLED)

root = tk.Tk()
frame = ttk.Frame(root)
frame.grid(column=0, row=0)

choice = tk.StringVar()
switch = False

button_a = ttk.Radiobutton(frame, text="A", variable=choice, value="A", command=select_door)
button_b = ttk.Radiobutton(frame, text="B", variable=choice, value="B", command=select_door)
button_c = ttk.Radiobutton(frame, text="C", variable=choice, value="C", command=select_door)

button_run = ttk.Button(frame, text="Run", command=run_sim, state=tk.DISABLED)

button_a.grid(column=0, row=0)
button_b.grid(column=1, row=0)
button_c.grid(column=2, row=0)
button_run.grid(column=1, row=1)

root.mainloop()

在选择替代选项之前,Run按钮未启用,当您选择一个选项时,您无法切换。当您按Run时,messagebox会询问您是否要切换。如果是,则再次启用选项,并将switch变量设置为True

当您选择不切换时,它会打印出您选择的内容,如果您切换它,则会打印一条说明该内容的行。然后它重置选项并将switch设置为False(这样它又重新开始了)。