0
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()

With this code i basically create a roll the dice simulator. In my actual code i give the function turn() player1/player2(which are class objects) so i can track whose turn it is. Thats why i call turn() 2 times in the while.

The problem is that the code after the first turn() isnt executed(until i manually close the root window which is weird) anymore. At my knowledge this should work.

I open the turn function which opens the diceAction function upon button press. diceAction() gives me the number and kills both windows. Then the second turn() should be called and the process continues until someone wins(which i havent implemented in this code). The print("Hi") isnt executed either. Am i missing something? You can copy this code and execute it yourself.

The S1
  • 39
  • 1
  • 5
  • You should not be calling `mainloop` more than once. That may not be the only problem, but that's definitely one problem. – Bryan Oakley Sep 03 '18 at 15:00
  • I need to use mainloop in the turn function because otherwise the windows would not "wait" for each other but open up infinitly. In the diceAction function i dont need the mainloop(in my actual code its without it) but it doesnt make any difference. If you could make the 2nd turn wait until the button is pressed, it would make things easier. – The S1 Sep 03 '18 at 15:05
  • I think you should take a look at this link: https://stackoverflow.com/questions/29211794/how-to-bind-a-click-event-to-a-canvas-in-tkinter – Moshe Slavin Sep 03 '18 at 15:07

1 Answers1

0

The short answer is "Infinite loops and tkinter don't play well together". The long answer is that you never escape window.mainloop(). I don't see a good enough reason that you need to have window.mainloop() and result.mainloop() running to justify the headache of multiple loops in tkinter.

A subjectively better way of doing this is to have the end of the first turn() trigger the start of the next one:

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()

I would recommend attempting to use OOP on a project like this instead of the global that I declared above.

Ethan Field
  • 4,646
  • 3
  • 22
  • 43
  • Shouldnt the window.destroy() remove the window anyway? The problem is that i call the turn function in my main program with something like: while 1: turn(player1) turn(player2) (sry i cant use line breaks here) I can remove the result.mainloop with no change but i need the window.mainloop because otherwise the windows wouldnt wait for each other(they will infinitely popup and overlay each other). – The S1 Sep 03 '18 at 15:29
  • Which is why I'm saying that an alternative approach where you trigger the start of the next cycle with the end of the first is how I would do this. Rather than create an infinite loop which doesn't mesh well with tkinter and is the reason why you need to have multiple `mainloop`s – Ethan Field Sep 03 '18 at 15:55