【问题标题】:Tkinter code isnt executed after destroying a window销毁窗口后不执行 Tkinter 代码
【发布时间】:2019-02-08 15:10:54
【问题描述】:
from tkinter import *
from random import *


root = Tk()

#A function to create the turn for the current player. The current player isnt in this code as it is not important
def turn():
    window = Toplevel()  
    dice = Button(window, text="Roll the dice!", bg= "white", command=lambda:diceAction(window))
    dice.pack()
    window.mainloop()

#a function to simulate a dice. It kills the function turn.
def diceAction(window):
    result = Toplevel()
    y = randint(1, 6)
    # i do something with this number
    quitButton = Button(result, text="Ok!", bg="white", command=lambda: [result.destroy(), window.destroy()])
    quitButton.pack()
    window.destroy()
    result.mainloop()


#A function to create the playing field and to start the game
def main():
    label1 = Button(root, text="hi", bg="black")

    label1.pack()


    while 1:
        turn()
        print("Hi")
        turn()


main()

root.mainloop()

使用这段代码,我基本上创建了一个掷骰子模拟器。在我的实际代码中,我给出了函数 turn() player1/player2(它们是类对象),这样我就可以跟踪轮到谁了。这就是为什么我会在一段时间内调用 turn() 2 次。

问题是第一个 turn() 之后的代码不再执行(直到我手动关闭了奇怪的根窗口)。据我所知,这应该有效。

我打开 turn 功能,在按钮按下时打开 diceAction 功能。 diceAction() 给我数字并杀死两个窗口。然后应该调用第二个 turn() 并且该过程继续进行,直到有人获胜(我没有在此代码中实现)。 print("Hi") 也没有执行。我错过了什么吗?您可以复制此代码并自行执行。

【问题讨论】:

  • 您不应多次致电mainloop。这可能不是唯一的问题,但这绝对是一个问题。
  • 我需要在 turn 函数中使用 mainloop,否则窗口不会“等待”彼此而是无限打开。在 diceAction 函数中,我不需要主循环(在我的实际代码中没有它),但它没有任何区别。如果你可以让第二轮等到按钮被按下,这会让事情变得更容易。
  • 我觉得你应该看看这个链接:stackoverflow.com/questions/29211794/…

标签: python tkinter


【解决方案1】:

简短的回答是“无限循环和tkinter 不能很好地配合使用”。长答案是你永远不会逃脱window.mainloop()。我没有看到足够好的理由让您需要运行 window.mainloop()result.mainloop() 来证明 tkinter 中的多个循环令人头疼。

一个主观更好的方法是让第一个turn()的结束触发下一个的开始:

from tkinter import *
from random import *

root = Tk()

global turnCount
turnCount = 0

def turn():
    window = Toplevel()
    dice = Button(window, text="Roll the dice!", bg="white", command=lambda:diceAction())
    dice.pack()

def diceAction():
    result = Toplevel()
    y = randint(1, 6)
    quitButton = Button(result, text="Ok!", bg="white", command=lambda: nextTurn())
    quitButton.pack()

def nextTurn():
    global turnCount
    turnCount = turnCount + 1
    for i in root.winfo_children():
        if str(type(i)) == "<class 'tkinter.Toplevel'>":
            i.destroy()
    turn()

def main():
    label1 = Button(root, text="hi", bg="black")
    label1.pack()
    turn()

main()

root.mainloop()

我建议尝试在这样的项目中使用 OOP,而不是我上面声明的 global

【讨论】:

  • 应该 window.destroy() 还是删除窗口?问题是我在我的主程序中调用了转函数,例如:while 1: turn(player1) turn(player2) window.mainloop 因为否则窗口不会相互等待(它们将无限弹出并相互覆盖)。
  • 这就是为什么我要说另一种方法,即在第一个周期结束时触发下一个周期的开始,这就是我将如何执行此操作的原因。而不是创建一个与 tkinter 不能很好结合的无限循环,这就是您需要多个 mainloops 的原因
猜你喜欢
  • 2020-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-07
  • 1970-01-01
  • 2017-03-09
  • 1970-01-01
相关资源
最近更新 更多