Как заставить окно Tkinter перейти на передний план?
Как заставить приложение Tkinter перейти на передний план? В настоящее время окно появляется за всеми моими другими окнами и не фокусируется.
Есть какой-то метод, который я должен вызывать?
12 ответов
Предполагая, что вы имеете в виду окна своего приложения, когда говорите "другие мои окна", вы можете использовать lift()
метод на топлевел или тк:
root.lift()
Если вы хотите, чтобы окно оставалось выше всех других окон, используйте:
root.attributes("-topmost", True)
куда root
это ваш Toplevel или Tk. Не забывайте -
перед "topmost"
!
Чтобы сделать его временным, отключите самый верхний сразу после:
def raise_above_all(window):
window.attributes('-topmost', 1)
window.attributes('-topmost', 0)
Просто перейдите в окно, которое вы хотите поднять в качестве аргумента, и это должно сработать.
Добавьте следующие строки перед mainloop():
root.lift()
root.attributes('-topmost',True)
root.after_idle(root.attributes,'-topmost',False)
Это прекрасно работает для меня. Когда окно генерируется, оно выходит вперед, и оно не будет всегда оставаться впереди.
Если вы делаете это на Mac, используйте AppleEvents, чтобы сфокусироваться на Python. Например:
import os
os.system('''/usr/bin/osascript -e 'tell app "Finder" to set frontmost of process "Python" to true' ''')
Что касается Mac, я заметил, что может быть проблема в том, что если запущено несколько графических интерфейсов Python, каждый процесс будет называться "Python", а AppleScript будет стремиться выдвинуть неправильный текст вперед. Вот мое решение. Идея состоит в том, чтобы получить список ID запущенных процессов до и после загрузки Tkinter. (Обратите внимание, что это идентификаторы процессов AppleScript, которые, по-видимому, не имеют отношения к их аналогам posix. Поймите.) Тогда странный человек будет вашим, и вы переместите его вперед. (Я не думал, что цикл в конце будет необходим, но если вы просто получите каждый процесс, чей ID является procID, AppleScript, очевидно, возвращает один объект, идентифицируемый по имени, что, конечно, является неуникальным "Python", поэтому мы вернемся к исходной точке, если я что-то упустил.)
import Tkinter, subprocess
def applescript(script):
return subprocess.check_output(['/usr/bin/osascript', '-e', script])
def procidset():
return set(applescript(
'tell app "System Events" to return id of every process whose name is "Python"'
).replace(',','').split())
idset = procidset()
root = Tkinter.Tk()
procid = iter(procidset() - idset).next()
applescript('''
tell app "System Events"
repeat with proc in every process whose name is "Python"
if id of proc is ''' + procid + ''' then
set frontmost of proc to true
exit repeat
end if
end repeat
end tell''')
В некоторой степени это комбинация различных других методов, это работает на OS X 10.11 и Python 3.5.1, работающих в venv, и должно работать на других платформах. Он также нацелен на приложение по идентификатору процесса, а не по имени приложения.
from tkinter import Tk
import os
import subprocess
import platform
def raise_app(root: Tk):
root.attributes("-topmost", True)
if platform.system() == 'Darwin':
tmpl = 'tell application "System Events" to set frontmost of every process whose unix id is {} to true'
script = tmpl.format(os.getpid())
output = subprocess.check_call(['/usr/bin/osascript', '-e', script])
root.after(0, lambda: root.attributes("-topmost", False))
Вы называете это прямо перед mainloop()
позвони, вот так:
raise_app(root)
root.mainloop()
В Mac OS X PyObjC предоставляет более чистый и менее подверженный ошибкам метод, чем выделение в osascript:
import os
from Cocoa import NSRunningApplication, NSApplicationActivateIgnoringOtherApps
app = NSRunningApplication.runningApplicationWithProcessIdentifier_(os.getpid())
app.activateWithOptions_(NSApplicationActivateIgnoringOtherApps)
Недавно у меня был такой же вопрос на Mac. Я объединил несколько ответов, используя @MagerValp
для Mac и @D K
для других систем:
import platform
if platform.system() != 'Darwin':
root.lift()
root.call('wm', 'attributes', '.', '-topmost', True)
root.after_idle(root.call, 'wm', 'attributes', '.', '-topmost', False)
else:
import os
from Cocoa import NSRunningApplication, NSApplicationActivateIgnoringOtherApps
app = NSRunningApplication.runningApplicationWithProcessIdentifier_(os.getpid())
app.activateWithOptions_(NSApplicationActivateIgnoringOtherApps)
root.mainloop()
Есть подсказка о том, как заставить окно Tkinter сфокусироваться при вызове mainloop() в функции Tkinter._test().
# The following three commands are needed so the window pops
# up on top on Windows...
root.iconify()
root.update()
root.deiconify()
root.mainloop()
Это самый чистый и правильный способ, который я нашел для этого, но он нужен только для систем Windows.
Этот ответ - заставить одно окно Tkinter всплывать поверх других окон Tkinter.
В моем приложении большое окно toplevel
который вызывает гораздо меньшее окно top2
который изначально появляется поверх toplevel
.
Если пользователь нажимает в toplevel
окно фокусируется и гораздо меньше задыхается top2
окно до toplevel
окно оттаскивается от него.
Решение - нажать кнопку в toplevel
запускать top2
еще раз. Вtop2
Функция open знает, что она уже запущена, поэтому просто поднимает ее наверх и фокусирует:
def play_items(self):
''' Play 1 or more songs in listbox.selection(). Define buttons:
Close, Pause, Prev, Next, Commercial and Intermission
'''
if self.top2_is_active is True:
self.top2.focus_force() # Get focus
self.top2.lift() # Raise in stacking order
root.update()
return # Don't want to start playing again
В macOS High Sierra, py3.6.4, вот мое решение:
def OnFocusIn(event):
if type(event.widget).__name__ == 'Tk':
event.widget.attributes('-topmost', False)
# Create and configure your root ...
root.attributes('-topmost', True)
root.focus_force()
root.bind('<FocusIn>', OnFocusIn)
Идея состоит в том, чтобы вынести это на передний план, пока пользователь не будет взаимодействовать с ним, то есть сфокусироваться.
Я попробовал принятый ответ, .after_idle()
, а также .after()
, Все они терпят неудачу в одном случае: когда я запускаю свой скрипт прямо из IDE, такой как PyCharm, окно приложения остается позади.
Мое решение работает во всех случаях, с которыми я столкнулся.
Еще одна строка (необходима для Python 3.11 и tkinter 8.6):
def lift_window(window):
window.attributes('-topmost', True)
window.update_idletasks() # get window on top
window.attributes('-topmost', False) # prevent permanent focus
window.focus_force() # focus to the window
Это поднимет окно вперед, а также сфокусирует внимание на окне.
def lift_window(window):
window.attributes('-topmost',True)
window.attributes('-topmost',False) # disable the topmost attribute after it is at the front to prevent permanent focus
window.focus_force() # focus to the window