How to intercept WM_DELETE_WINDOW on OSX using Tkinter - python

I'm trying to keep a Toplevel window from being closed in OSX by intercepting window manager WM_DELETE_WINDOW event.
#!/usr/bin/env python
from Tkinter import *
def speak():
print "woof"
root = Tk()
root.title("root")
win = Toplevel()
win.title("win")
win.protocol('WM_DELETE_WINDOW', speak)
root.mainloop()
When I run this I get two pop up windows titled "root" and "win". If I click on the red "x" close button on "win" to close the window, prints "woof" and then closes. However, if I run this same code on windows "win" stays open and keeps printing "woof" every time I click the red "x" close button.
How can I keep the Toplevel window from closing on OSX when I click the red "x" close button?

See the reply to Python Issue 12584. It appears to be a bug in the very buggy Cocoa Tcl/Tk 8.5 that Apple shipped with OS X 10.6. Don't use it or the Apple-supplied Pythons in 10.6 if you are using Tkinter or anything that uses Tkinter, like IDLE. More info here.

Related

Python tkinter main window closes all other windows too, why?

I made a gui programm with Tkinter. In the program are several buttons which open new main tkinter windows but when i click on the 'x' of one of these windows all the other ones close too although they are different windows. Only the Buttons, which cause the new tkinter main windows, are in the same main window.
please help :))
This is how tkinter is designed to work. When you destroy a window, all of its children are destroyed. Since everything is a child of the root window or one of its children, when you destroy the root window all other widgets are destroyed along with it.

How to close or destroy Tkinter window on Mac

How can I destroy Tkinter window on Mac?
My code works fine with window and I could easily exit by clicking on X but on Mac, because of mainloop() and there's no X, I can't close.
So I tried to create shortcut or hotkey to easily close the window. (or tell me if there's other way around)
import tkinter
window=tkinter.Tk()
window.title("tkinter")
window.geometry("640x400+100+100")
window.resizable(False, False)
window.mainloop()
This is my Code. I could easily close on Window but not on Mac.
Maybe if I insert
def close_window(self):
window.destroy()
window.bind('<Control-q>',close_window)
I could simply close by pressing Ctrl+Q but idk why this also returns error.
Please help me. Thank you

Python, tkinter, window freeze after mainloop (on MacOSX)

Could not find anything on this topic in other posts (or maybe I just completely did not understand how tkinter works).
I have a very simple setup where after closing my window, a Shell script is supposed to be executed. The problem (at least on MacOSX) is that while the shell script runs, the window freezes and stays open.
Minimal working example:
from tkinter import Tk, Label
from subprocess import call
# GUI
root=Tk()
Label(root,text="Test window").pack()
root.mainloop()
# call
call("sleep 10", shell=True)
# Window stays open and freezes until sleep command returns
Am I missing something?
Thanks! Jan

Python 3.6 crashes when clicking exit in Tkinter window Mac OSX

When trying to close my tkinter window using the red 'x' button (top left) the window doesn't close and python crashes(colour wheel).
(note this is across all of my Tkinter apps, not just the one shown)
Here is an image of my code:
Here is the crashed white box, neither "quit" or red "x" works. It doesn't show up in the screenshot but the spinning colour wheel is visible whenever I hover over my window. I have to force quit due to "Python not responding".
Got me thinking when I run python in the shell there's an error message: TK Tcl. Maybe unstable.
I suggest to try master.destroy instead of frame.quit for the callback of the Quit button, and give us feedback whether it changes anything

tkMessageBox popup invisible when run from desktop, visible when run from boot

I am trying to write a program that allows the user to press different buttons in a full screen Tkinter GUI. The operations these buttons preform does not matter for my question, but I am having trouble creating a popup dialogue (askokcancel) to confirm that the user wants to press a button, then run the rest of that buttons code normally if "ok" is pressed. Currently, I have this program running from boot through the /etc/profile file, accessed via
sudo nano /etc/profile
Here I change the directory to the folder containing my python file and have it load my code, and upon booting up it loads my buttons correctly and upon pressing the correct button the popup window appears over the full screen window. However, when I try to run my code through the desktop shell, upon pressing the button, the popup window DOES appear, but is hidden behind the root window. I am not able to click anywhere else, and pressing "tab" and "enter" allows me to navigate between the two choices and pick one, but without being able to see it. I have buttons printing words in the shell, so I know the popup window is actually there.
The full screen makes use of the overrideredirect function, hiding the task bar and other options. When this is set to FALSE, the popup works as intended, but I am trying to make the GUI be the only thing on the screen.
Here is a condensed version of my code:
from Tkinter import*
import tkMessageBox
class Application(Frame):
def run(self):
tkMessageBox.askokcancel("Run Confirmation!", "Are you sure?")
print "RUN Code Intitates"
def createWidgets(self):
self.button1 = Button(self,height=15,width=20)
self.button1["command"] = self.run
self.button1.pack({"side": "left"})
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.createWidgets()
root = Tk()
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
root.overrideredirect(1)
root.geometry("%dx%d+0+0" % (800, 480))
app = Application(master=root)
app.mainloop()
root.destroy()
I am by no means a computer science major and have only been working with raspberry pi, tkinter, and python for a couple weeks, so if I am missing something basic I apologize. I am using an 8" touchscreen display made for raspberry pi as my screen.
According to the tcl/tk documentation:
Setting the override-redirect flag for a window causes it to be
ignored by the window manager; among other things, this means that the
window will not be reparented from the root window into a decorative
frame and the user will not be able to manipulate the window using the
normal window manager mechanisms
So the window does not always behave has expected (it is less the case in Windows). For instance, in Linux, the window does not get keyboard focus (python tkinter overrideredirect; cannot receive keystrokes (Linux)).
If what you really care about is to have a fullscreen GUI, just replace
root.overrideredirect(1)
by
root.attributes('-fullscreen', True)
and the window will behave normally so the message box will appear on top of the main window.
Another possibility in Linux is to replace
root.overrideredirect(1)
by
root.attributes('-type', 'dock')
This tells the window manager to treat the window as a dock, and at least in XFCE, it results in a window with no decorations, always on top of the other windows, but the message box does appear on top of it.

Categories

Resources