How to put a tkinter window on top of the others?
Asked Answered
H

9

39

I'm using Python 2 with Tkinter and PyObjC, and then I'm using py2app.

The program is working fine, but the window starts as hidden whenever I open the program, so it doesn't appear until I click on the icon on the dock to bring it up.

Is there any way to control this, make the window to be on top of other windows that were open when the application is starting?

Just to clarify, it doesn't have to be on the top for the whole time the application is running. I just need it to be on top of other windows when it starts.

Hagy answered 1/1, 2012 at 3:15 Comment(1)
Possible duplicate of How to make a window jump to the front?Darrendarrey
V
15

If I take the code you give and add the first and last line you get:

from tkinter import *

root = Tk() 
root.title("app")
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
root.geometry("550x250+%d+%d" % (screen_width/2-275, screen_height/2-125))
root.configure(background='gold')
root.lift()

mainloop()

Test it. I get the window as expected. Do you get something else? If this works then somewhere in the code you are telling it to do that. If it does the same thing as your real program then your window manager is doing it. This is the best I can do without more information.

Edit:

On OSX (espicially versions using aqua) tkinter's windows may be displayed behind those that are already open (this has a bug report here: http://bugs.python.org/issue9384 but has been closed as will not fix). The addition of the root.lift() command has been included to bring the window to the front of the stack in those cases and is harmless in all others.

Viperous answered 1/1, 2012 at 4:9 Comment(5)
I got it solved. It was because my code had a period (".") in it's file name. When I removed the period from the file name the window appeared on top fine, though I'm not sure how they relate. Thanks anyway!Hagy
Actually, now it's not showing on top again. I have no idea why it goes back and forth, but I'm guessing that something's wrong with the window manager, obviously since it's doing that when I didn't even change anything in the code. Is there a way to force the window to be on top with PyObjC? I've been searching it but there hasn't been any good answer... @ViperousHagy
I'm using Lion (10.7.2). I really don't get what I'm doing wrong to make the app to not display in the front ;( @ViperousHagy
Hmm.. so it is a bug... I tried the lift method but it's not bringing my window though.. I tried placing it in different places and/or in multiple places but it still wouldn't place it above for some reason. Thanks a lot though! @ViperousHagy
I have the same problem with OS 10.6, and without using PyObjC.Scorch
N
70

I know this is an old question but I found it weird that no one came up with the simple solution I had,

app = SampleApp()

app.attributes('-topmost', True)
app.update()
app.attributes('-topmost', False)

app.mainloop()
Nanceenancey answered 12/7, 2017 at 18:15 Comment(7)
This is the best answer (works fine on osx as well). Thank you.Tucker
This worked better than anything else I could find. ThxCele
This works great to get the window to appear on top, but it appears out of focus (until I click on it). What if I want it to wake up in-focus?Bettinabettine
Continuing my above comment: I tried root.force_focus() but that did not work. (Perhaps force_focus only works with windows that have inputtable fields??)Bettinabettine
This is the only solution that worked for me (Win 7, Py 3.7). @DanielGoldfarb isnt it focus_force()?Kolk
@Nils, I don't know. I imagine I saw "force_focus" on a posting somewhere; perhaps that was the problem. In the end, based on information in yet another posting somewhere I ending up simply doing this at the top of my script: import matplotlib matplotlib.use('TkAgg') ## (The above must be done before importing pyplot) When I added those two lines at the top of my script, it fixed everything (plot window appears on top and in focus from the start). (MacOS 10.13.6, Py 3.6.5, Matplotlib 2.2.2)Bettinabettine
@DanielGoldfarb nice to hear you solved it elsewhere :-) My solution has been to .focus_force() both the container window and the child text entry widget. Setting it on the text entry alone didnt focus it. The reason is (probably) that i have configured my system to auto(un)focus windows when hovering (out) with the mouse. So the tkinter window gets created but immediately loses focus again when the mouse is not in it. So the child entry never gets the focus. Explicitely .focus_force()ing the parent window solves this.Kolk
D
29

I got into same issue today. OSX LION 10.7.2. Add this code before mainloop() solves the issue.

root.call('wm', 'attributes', '.', '-topmost', '1')

but the window always remains on top of the others until you close it. For real solve, we need to make it an app bundle, with py2app.

Durston answered 3/3, 2012 at 5:42 Comment(1)
Any idea how to make it so it's only on top of all other windows of the program (rather than on top of windows of other programs, too)?Baynebridge
V
15

If I take the code you give and add the first and last line you get:

from tkinter import *

root = Tk() 
root.title("app")
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
root.geometry("550x250+%d+%d" % (screen_width/2-275, screen_height/2-125))
root.configure(background='gold')
root.lift()

mainloop()

Test it. I get the window as expected. Do you get something else? If this works then somewhere in the code you are telling it to do that. If it does the same thing as your real program then your window manager is doing it. This is the best I can do without more information.

Edit:

On OSX (espicially versions using aqua) tkinter's windows may be displayed behind those that are already open (this has a bug report here: http://bugs.python.org/issue9384 but has been closed as will not fix). The addition of the root.lift() command has been included to bring the window to the front of the stack in those cases and is harmless in all others.

Viperous answered 1/1, 2012 at 4:9 Comment(5)
I got it solved. It was because my code had a period (".") in it's file name. When I removed the period from the file name the window appeared on top fine, though I'm not sure how they relate. Thanks anyway!Hagy
Actually, now it's not showing on top again. I have no idea why it goes back and forth, but I'm guessing that something's wrong with the window manager, obviously since it's doing that when I didn't even change anything in the code. Is there a way to force the window to be on top with PyObjC? I've been searching it but there hasn't been any good answer... @ViperousHagy
I'm using Lion (10.7.2). I really don't get what I'm doing wrong to make the app to not display in the front ;( @ViperousHagy
Hmm.. so it is a bug... I tried the lift method but it's not bringing my window though.. I tried placing it in different places and/or in multiple places but it still wouldn't place it above for some reason. Thanks a lot though! @ViperousHagy
I have the same problem with OS 10.6, and without using PyObjC.Scorch
H
15

For OS X 10.8.3, the combination of the answers provided by vdbuilder and user2435139 did the trick for me, i.e.

self.root.lift()
self.root.call('wm', 'attributes', '.', '-topmost', True)
self.root.after_idle(self.root.call, 'wm', 'attributes', '.', '-topmost', False)

called before

self.root.mainloop()
Hereditable answered 2/7, 2013 at 23:28 Comment(0)
B
5

More for mac OS users. Although the above solutions seem to display correctly, the app is still put at "the end of the stack" from the Finder's point of view. As can be seen with the Cmd+Tab switcher, or simply observing that python doesn't get the focus.

Solution from username fixing it all (again, for mac OS):

import os
os.system('''/usr/bin/osascript -e 'tell app "Finder" to set frontmost of process "Python" to true' ''')

Maybe surround that with something like

import platform
if "Darwin" in platform.system():
    # apply fix
Biforate answered 16/12, 2013 at 18:32 Comment(1)
Actually, using this code, makes the other offered solutions redundant. Although, they might have more benefit on other platforms than OS X, haven't tried yet. Thanks!Chunky
F
3

I modified the above solution and these 2 lines work for me on OSX. It brings the window to the front, but without making the window behave as Always on Top.

root.call('wm', 'attributes', '.', '-topmost', True)
root.after_idle(root.call, 'wm', 'attributes', '.', '-topmost', False)
Faqir answered 30/5, 2013 at 5:35 Comment(1)
Not working in Mac OS 10.11.2. You need the root.lift(), as in @jjaderberg's answer.Nephrectomy
W
1

The osascript trick Arnaud P could have problems, if there is more than one process with the application title ‘Python’; additionally, it will not work for Python 3 processes (needs to be called ‘Python3’ then.

However, I found another trick that can solve the problem by using the process id.

import os
script = 'tell application "System Events" \
  to set frontmost of the first process whose unix id is {pid} to true'.format(pid=os.getpid())
os.system("/usr/bin/osascript -e '{script}'".format(script=script))
Whiteeye answered 9/7, 2016 at 23:15 Comment(1)
This is the best solution for OS X that brings the window to front and puts it first in Finder list (Cmd+Tab).Trilateration
G
1

In my case, if there was no update() call, the window would not pop above the terminal. This is what ended up working:

def raise_above_all(window):
    window.attributes('-topmost', True)
    window.update()
    window.attributes('-topmost', False)
Ganger answered 25/5, 2021 at 15:39 Comment(0)
M
1

About ms-windows we dont need to extra code (for go to top window) just need to :

window.attributes('-topmost',True)
Marrakech answered 15/7, 2022 at 19:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.