1

I have a problem similar to this post: Exit program within a tkinter class

My variation on the problem involves the wait_variable being used on a button to control "stepping forward" in an app, but also allowing the app to close cleanly.

See my code below:

# To see output unbuffered:
#   python -u delete_win_test.py

import tkinter as tk
from tkinter import *


class GUI(Tk):
    def __init__(self):
        super().__init__()

        # Close the app when the window's X is pressed
        self.protocol("WM_DELETE_WINDOW", self.closing)

        # When this var is set to 1, the move function can continue
        self.var = tk.IntVar()

        # Close the app if the button is pressed
        button = tk.Button(self, text="Exit",
                           command=self.destroy)
        button.place(relx=.5, rely=.5, anchor="c")

        # Step forward
        self.step_button = tk.Button(self, text="Step",
                                     command=lambda: self.var.set(1))
        self.step_button.place(relx=.5, rely=.75, anchor="c")

    def move(self):
        print("doing stuff")  # simulates stuff being done
        self.step_button.wait_variable(self.var)
        self.after(0, self.move)

    def closing(self):
        self.destroy()


app = GUI()
app.move()
app.mainloop()
  • The window shows correctly
  • "Stepping forward" works because "doing stuff" prints to terminal on button click
  • Exiting the window by both pressing X or using the "exit" button both work

The problem: the Python app never exits from the terminal and requires a closing of the terminal.

How can I make the Python program exit cleanly so the user does not need to close and re-open a new terminal window?

Related references for animation, etc:

UPDATE (the solution):

(Credit to both response answers below)

         # Close the app if the button is pressed
         button = tk.Button(self, text="Exit",
-                           command=self.destroy)
+                           command=self.closing)
         button.place(relx=.5, rely=.5, anchor="c")
 
         # Step forward
...
     def closing(self):
         self.destroy()
+        self.var.set("")
+        exit(0)

This allows the native window's "X" to close the window and the Tk button to close the window while still closing the Python app cleanly in the terminal.

2
  • Why dont you set self.var to a special int in your closing method and dont continue with move if this special int is set? Working with a if statement solves this anyhow and shouldnt be too hard to solve for you. Commented Nov 10, 2021 at 17:09
  • Hi @Atlas435, I see what you mean with self.var, however can you explain what you mean by the if statement? Is that a separate solution or related to self.var? Commented Nov 10, 2021 at 17:41

2 Answers 2

0

Your closing function needs to set the variable to cause the app to stop waiting.

def closing(self):
    self.destroy()
    self.var.set("")
Sign up to request clarification or add additional context in comments.

4 Comments

Hi Bryan, thank you for the response, but this did not work for me. The Python app still does not exit cleanly in the terminal even though the window closes (using X or the close button). Tested on both Windows Git Bash and Mac OSX.
@masao: that's odd. It works for me on OSX.
Hi again Bryan, here's my environment: tk==0.1.0 toml==0.10.2 Python version: Python 3.9.4 Does this match your environment?
Solution posted in original post! Thank you so much!
0

in the closing function, you need to call exit to exit the program.

def closing(self):
    self.destroy() #closes tkinkter window
    exit(0) #exits program

1 Comment

Thanks! I combined this with other answers and found the solution (see original post)!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.