root.overrideredirect and <Any-KeyPress> binding - python

I would like the following program to quit on <Any-KeyPress> event.
from tkinter import *
root = Tk()
root.overrideredirect(True)
root.bind('<Any-KeyPress>', lambda e: root.destroy())
root.mainloop()
This works fine on Windows OS. However this does not work on Ubuntu unless I remove the line root.overrideredirect(True) from the above code.
Is this the intended behavior ?
Or is there a way whereby I can make my program to work while still using root.overrideredirect(True) ?
Edit
I just saw a similar question here at SO, where Bryan Oakley suggests using root.focus_force() but it does not help.
Edit 2
I used root.attributes('-fullscreen', True) instead of root.overrideredirect(True) as suggested here and that seems to work now.

Try this:
from tkinter import *
root = Tk()
root.bind('<Any-KeyPress>', quit())
root.mainloop()
Assuming that you want the program to quit, keep the code. If you just want to clear the screen, just use root.destroy() rather that quit(). Using root.overrideredirect(True) will NOT work on Ubuntu.

Related

Why does a Toplevel window get destroyed when the main window is minimized?

from tkinter import *
root = Tk()
root.geometry("500x500")
toplevel = Toplevel()
toplevel.attributes("-toolwindow" , 1)
mainloop()
In this code, when I minimize the main window and open it again, the toplevel window disappears.
Here's an image(GIF) describing my problem:
Is there any way to avoid this?
It would be great if anyone could help me out.
(OS: Windows 10,
Python version: 3.9.1,
Tkinter version: 8.6)
The toolwindow attribute is specifically designed to make the window hide when the root window hides. If you don't want that behavior, don't set that attribute.
With the help of acw1668, I found the answer by myself.
The top-level window does not disappear; instead, it just goes behind all the windows.
There is a way to bring it back:
from tkinter import *
root = Tk()
root.geometry("500x500")
def bring_window_back(e):
toplevel.attributes('-topmost' , 1)
toplevel.attributes('-topmost' , 0)
toplevel = Toplevel(root)
toplevel.attributes("-toolwindow" , 1)
root.bind("<Map>" , bring_window_back)
mainloop()
Note: The <Map> binding may not work properly on linux. If you are searching for a solution for this, please see: Binding callbacks to minimize and maximize events in Toplevel windows
Hope this helps you all.

With two tkinter windows, script does not execute after one's mainloop

I have a script which has two tkinter.Tk() objects, two windows. One is hidden from the start (using .withdraw()), and each has a button which hides itself and shows the other (using .deiconify()). I use .mainloop() on the one shown in the beginning. Everything works, but when I close either window, the code after the mainloop() doesn't run, and the script doesn't end.
I suppose this is because one window is still open. If that is the case, how do I close it? Is it possible to have a check somewhere which closes a window if the other is closed?
If not, how do I fix this?
The essence of my code:
from tkinter import *
window1 = Tk()
window2 = Tk()
window2.withdraw()
def function1():
window1.withdraw()
window2.deiconify()
def function2():
window2.withdraw()
window1.deiconify()
button1 = Button(master=window1, text='1', command=function1)
button2 = Button(master=window2, text='2', command=function2)
button1.pack()
button2.pack()
window1.mainloop()
Compiling answers from comments:
Use Toplevel instead of multiple Tk()s. That's the recommended practice, because it decreases such problems and is a much better choice in a lot of situations.
Using a protocol handler, associate the closing of one window with the closing of both. One way to do this is the following code:
from _tkinter import TclError
def close_both():
for x in (window1,window2):
try:
x.destroy()
except TclError:
pass
for x in (window1,window2):
x.protocol("WM_DELETE_WINDOW", close_both)

Python 3 tkinter: focus_force on messagebox

I'm running python 3 code in background which should show a popup window in some situations. I'm using tkinter for this:
import tkinter as tk
from tkinter import messagebox
def popup(message, title=None):
root = tk.Tk()
root.withdraw()
root.wm_attributes("-topmost", 1)
messagebox.showinfo(title, message, parent=root)
root.destroy()
popup('foo')
The ok-button in this infobox should get the focus automatically when popping up. Sadly I'm not able to do this. I tried root.focus(), but it does not help. Any ideas how to solve that? TIA
BTW: The code should be platform independent (Linux and Windows).
Edit:
Maybe I missunderstood the focus keyword and I should clarify my question:
root = tk.Tk()
root.focus_force()
root.wait_window()
When calling the code above the root window is active, even if I worked in e.g. the browser before. Is this also possible for messagebox.showinfo? Adding root.focus_force() in the popup function does not help.
Is this even possible? Or is it necessary to create my own root window? I really like the appearance of the messagebox with the icon.
Edit 2:
Here is a video: https://filebin.net/no195o9rjy3qq5c4/focus.mp4
The editor is the active window, even after the popup was shown.
In Linux I it works as expected.
You can use the default argument in the messagebox function.
default constant
Which button to make default: ABORT, RETRY, IGNORE, OK, CANCEL, YES, or NO (the constants are defined in the tkMessageBox module).
So, here is an example to highlight the "ok" button.
import tkinter as tk
from tkinter import messagebox
def popup(message, title=None):
root = tk.Tk()
root.withdraw()
messagebox.showinfo(title, message, parent=root, default = "ok")
root.destroy()
popup('foo')
Hope this helps!

Tkinter simpledialog boxes not getting focus in Windows 10 with Python3

In the code below, the first dialog box gets focus immediately, so the user can just type an answer and press enter. In the second one, that doesn't seem to happen when running in Windows. Running Raspbian 9, both windows get focus when they open.
Is there any way I can get both windows to get focus when they open in Windows?
import tkinter as tk
from tkinter import simpledialog
root = tk.Tk()
root.withdraw()
answer1 = simpledialog.askstring("Test1","This one gets focus when it opens",parent=root)
answer2 = simpledialog.askstring("Test2","This one doesn't",parent=root)
I have watched this question for a few days now hoping someone might shed some light on this issue. I'm running Python 3.6.5 under windows 10 and get the same problem.
I have tried several different things but it seems Microsoft does things their own way. I have finally found a thing that works, but only if you don't hide the root window:
import tkinter as tk
from tkinter import simpledialog
root = tk.Tk()
#root.withdraw() # This does not work if you hide the root window
root.update_idletasks()
answer1 = simpledialog.askstring("Test1","This one gets focus",parent=root)
root.update_idletasks()
answer2 = simpledialog.askstring("Test2","This one doesn't",parent=root)
I found the following worked (with a small flicker of the root window on destroy()):
root = tk.Tk()
root.withdraw()
filename = filedialog.askopenfilename()
root.deiconify()
root.destroy()

How to make Toplevel() widget appear above main root window?

I have made a Toplevel widget but when it pops up it always appears below my root window. Is there an easy way I can make it come to the top most level when it pops up?
you can use the .lift() method on a Toplevel widget:
import tkinter
root = tkinter.Tk()
root.title("root")
top = tkinter.Toplevel(root)
top.title("top")
top.lift(root)
root.mainloop()
according to this documentation you should be able to just use top.lift() to raise above all other windows but it didn't seem to work for me.
Edit: calling top.lift() without arguments does work when called during the mainloop, although since this question was specifically when starting the program that isn't very useful.
try attributes
import tkinter
root = tkinter.Tk()
root.title("root")
top = tkinter.Toplevel(root)
top.attributes('-topmost', 'true')
top.title("top")
root.mainloop()

Categories

Resources