Home > Back-end >  Spyder not terminating tkinkter mainloop()
Spyder not terminating tkinkter mainloop()

Time:12-16

I am starting with python and I'm using Spyder 3.9.13 with Python 3.9

When beginning with the GUI design I have run in one problem: Spyder runs the script just once and jams in infinite loop.

Code that fails:

import tkinter as TK
ws=TK.Tk()
print('Foo')
ws.mainloop()
print('Bar')

When run from Spyder the window emerges and only the Foo is printed. When run from command line, the Bar is printed when the window is closed, as expected.

Adding the manloop killing button does not help either, the behaviour is the same.

import tkinter as TK
ws=TK.Tk()

Button(
    ws,
    text='Exit',
    command=lambda:ws.destroy()
).pack(expand=True)

print('Foo')
ws.mainloop()
print('Bar')

When the destroy() method call is replaced by quit() call the Bar is printed but the window is not closed.

The little expanded code works partially as intended:

import tkinter as TK

class FooBar:
    def __init__(self,Name):
    self.win=TK.Tk()
    self.win.title=(Name)

    def terminate(self):
        self.win.quit()
        self.win.destroy()

ws=FooBar('FooBar')

TK.Button(
    ws.win,
    text='Exit',
    command=lambda:ws.terminate()
).pack(expand=True)

print('Foo')
ws.win.mainloop()
print('Bar')

Even this code runs differently from the Spyder and from the command line. Form command line the Bar is printed no matter how the window is terminated; by the Exit button or the cross button. On the other hand, Spyder closes the window and prints Bar only if the window is closed by the Exit button. When closed as a window, the Bar is not printed and it is still stuck in the loop.

What causes this behaviour and how can I prevent it?

CodePudding user response:

Please give this a try

import tkinter as TK


class FooBar:
    def __init__(self, name):
        self.win = TK.Tk()
        self.win.title = name
        self.win.protocol("WM_DELETE_WINDOW", self.terminate)

    def terminate(self):
        self.win.destroy()


ws = FooBar('FooBar')

TK.Button(
    ws.win,
    text='Exit',
    command=ws.terminate
).pack(expand=True)

print('Foo')
ws.win.mainloop()
print('Bar')

self.win.protocol("WM_DELETE_WINDOW", self.terminate) might help with this. self.win.destroy() should work but I don't have experience with Spyder to be sure about it.

OP's EDIT:

It seems it was the protocol("WM_DELETE_WINDOW") missing.

import tkinter as TK

ws=TK.Tk()
ws.protocol("WM_DELETE_WINDOW", ws.destroy)

TK.Button(
    ws,
    text='Exit',
    command=ws.destroy
).pack(expand=True)

print('Foo')
ws.mainloop()
print('Bar')

Now the Bar is printed after the window is closed, no matter how, when called from both Spyder and Command Line.

  • Related