【问题标题】:Making Tkinter wait untill button is pressed让 Tkinter 等到按钮被按下
【发布时间】:2017-12-01 02:34:58
【问题描述】:

我有一个游戏,当一个按钮被创建时,我需要我的程序只显示这个屏幕,直到他们按下“下一级”所有这些代码都在一个 while 循环中,所以在一个大的 while 循环中控制游戏。

......

if game.playerDistance >= game.lowerBound() and game.playerDistance <= game.upperBound():
        game.level += 1

        showLevelResults(game)

        #NextLevelButton
        btnNextLevel = Button(root,
                    #Random Config
                    command = nextLevel,
                    )
        btnNextLevel.place(x=1003, y=492, anchor=NW,  width=247, height=78)

        updateMainScreen()

        while nextLev == False:
            #What Do I put in here to force a wait
    else:

......

nextLev = False
def nextLevel():
    nextLev = True

...

目前这将它保持在 while 循环中,当按下按钮时没有任何变化,我使用 time.sleep(1) 让它等待并让它打印等待 btn 按下,但是这会向控制台发送垃圾邮件,并且当按下按钮仍然不会改变屏幕。

def showGameSurvival():

game = gamemode_normal()

while game.health != 0:
    game.next = False 
    clearScreen()
    changeBackground("Survival")

    #Placing Labels on the screen for game.....

    #... Health
    root.update()

    lblCountDownLeft = Label(root, bg="White", fg="Green", font=XXLARGE_BUTTON_FONT)
    lblCountDownLeft.place(x=169, y=350, anchor=CENTER)
    lblCountDownRight = Label(root, bg="White", fg="Green", font=XXLARGE_BUTTON_FONT)
    lblCountDownRight.place(x=1111, y=350, anchor=CENTER)
    #CountDown
    count = 7
    while count > 0:                
        lblCountDownLeft['text'] = count
        lblCountDownRight['text'] = count
        root.update()
        count -= 1
        time.sleep(1)

    lblCountDownLeft.destroy()
    lblCountDownRight.destroy()
    root.update()
    #Num on left x=169, right, x=1111 y=360

    game.measureDistance()
    if game.playerDistance >= game.lowerBound() and game.playerDistance <= game.upperBound():
        game.level += 1
        clearScreen()
        changeBackground("Survival")
        graphicalDisplay(game)

        #NextLevelButton
        btnNextLevel = Button(root,
                    bg= lbBlue,
                    fg="white",
                    text="Level" + str(game.level),
                    font=SMALL_BUTTON_FONT,
                    activebackground="white",
                    activeforeground= lbBlue,
                    command= lambda: nextLevel(game),
                    bd=0)
        btnNextLevel.place(x=1003, y=492, anchor=NW,  width=247, height=78)
        root.update()
        while game.next == False:
            print(game.next)
    else:
        game.health -= 1

    if game.allowance > 4:
        game.allowance = int(game.allowance*0.9)

#when game is over delete the shit        
if game.health == 0:
    del game

下一个按钮现在调用这个函数:def nextLevel(game): game.next = True

【问题讨论】:

  • 不要在 tkinter 中使用 sleep()。请改用after()。使用 sleep 将暂停整个 tkinter 实例,并且可能没有按照您认为的那样做。
  • 请创建一个minimal reproducible example。作为一般规则,您应该不惜一切代价避免自己的游戏循环,因为 tkinter 已经有一个无限循环。我们需要看看您是如何实现游戏循环的。
  • 嘿,我已经更新了我的问题并删除了我的代码中许多不重要的部分。我只需要我的屏幕保持原样,在创建该按钮后没有任何变化,并且在单击该按钮之前一直保持这种状态,非常感谢!

标签: python python-3.x user-interface button tkinter


【解决方案1】:

让 tkinter 等待某个事件的最简单方法是调用“等待”函数之一,例如 wait_variablewait_windowwait_visibility

在您的情况下,您希望等待按钮单击,因此您可以使用wait_variable,然后让按钮设置变量。当您单击按钮时,变量将被设置,当变量被设置时,对wait_variable 的调用将返回。

例如:

import tkinter as tk
root = tk.Tk()
...
var = tk.IntVar()
button = tk.Button(root, text="Click Me", command=lambda: var.set(1))
button.place(relx=.5, rely=.5, anchor="c")

print("waiting...")
button.wait_variable(var)
print("done waiting.")

注意:你不必使用IntVar——任何特殊的 Tkinter 变量都可以。此外,无论您将其设置为什么,该方法都会等到它发生变化。

【讨论】:

  • 这听起来正是我正在寻找的东西,但是我遇到了一点错误:我在你的示例中将 tk 更改为 Tk、root 和 tk,并且每个都有错误,在我的程序顶部我有 root = Tk(),为什么我会遇到这些错误,我应该使用哪一个? var = Tk.IntVar(): AttributeError: type object 'Tk' has no attribute 'IntVar' ||| var = root.IntVar(): AttributeError: '_tkinter.tkapp' 对象没有属性 'IntVar' ||| var = tk.IntVar(): NameError: name 'tk' is not defined
  • 我已经通过 var = IntVar() 修复了它 非常感谢 Bryan 我不知道这件事,它对我的​​游戏非常有用!非常感谢!!
【解决方案2】:

只是想添加评论,但没有足够的声誉。我无法让 wait_variable(var) 在按钮上为我工作。我不得不在我的框架上使用它。我猜这是 Python 2 和 3 之间的变化。

这是我得到的错误:

Traceback(最近一次调用最后一次):

文件“AutoPlotHydroData2.py”,第 434 行,在 btnOK.wait_variable(okVar) AttributeError: 'NoneType' 对象没有属性 'wait_variable'

我的工作代码如下:

    # Launch frame to collect needed input values
    myFrame = tk.Tk()
    myFrame.configure(background='lightblue')

    # Add some widgets

    # OK Button
    okVar = tk.IntVar()
    btnOK = tk.Button(myFrame, text="Submit", pady=5, font=("Arial Bold", 10),
        bg='lightgray', command=lambda: okVar.set(1)).grid(row=14, column=0)

    # Show frame
    myFrame.tkraise()

    # Wait for OK button to be pressed
    #btnOK.wait_variable(okVar) - this didn't work
    myFrame.wait_variable(okVar)

    # Close frame
    myFrame.destroy()

我在循环中使用此代码来处理多个文件。希望这对某人有所帮助。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2011-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-25
  • 1970-01-01
  • 2020-08-17
相关资源
最近更新 更多