【问题标题】:Tkinter Buttons: How make sure certain buttons have been pressed before running the main part of your scriptTkinter 按钮:如何确保在运行脚本的主要部分之前已按下某些按钮
【发布时间】:2016-01-30 23:19:47
【问题描述】:

我为这个措辞糟糕的问题道歉,我只是想不出更好的方式来表达我的问题。我正在编写一个使用交互式 GUI 演示 Monty Hall 问题的脚本。在我的第一帧中,我有 3 个按钮,分别标记为“A 门”、“B 门”和“C 门”。在这 3 个按钮下方,我还有另外 2 个标记为“切换选择”和“保留选择”的按钮。

代表“门”的 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)

【问题讨论】:

  • 你需要一些带有True/False的变量来控制它。
  • 您可以在类的方法中创建MontyHallSim 的所有全局属性,然后通过self.attribute_name 引用。同样的技术将允许您添加额外的变量,如 @furas 建议的,以跟踪用户所做的事情和游戏模拟的状态。然后,您可以添加一个新方法来执行您想要完成的检查并在 run_sim() 方法之前调用它或从该方法调用它(方法可以调用其他方法)。

标签: python python-3.x button tkinter


【解决方案1】:

您可以禁用 (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(这样它又回到了从头开始)。

【讨论】:

  • 感谢大家的帮助,我能够从您的所有建议中找出解决方案。我能够让我的程序按照我想要的方式运行。我仍在调整我的编码以简化它并使其整体更好。再次感谢您的帮助,真的很感激!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-01-18
  • 2020-01-01
  • 2016-12-31
  • 2018-01-28
  • 2021-06-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多