Как заставить окно Tkinter перейти на передний план?

StackOverflow https://stackoverflow.com/questions/1892339

  •  19-09-2019
  •  | 
  •  

Вопрос

Как мне заставить приложение Tkinter перейти на передний план?В настоящее время окно отображается позади всех моих других окон и не получает фокуса.

Есть ли какой-то метод, который я должен вызывать?

Это было полезно?

Решение

Предполагая, что вы имеете в виду окна вашего приложения, когда говорите "мои другие окна", вы можете использовать lift() метод на Высшем уровне или Тз:

root.lift()

Если вы хотите, чтобы окно оставалось выше всех других окон, используйте:

root.attributes("-topmost", True)

Где root это ваш Топовый уровень или Тз.Не забывайте о - перед "topmost"!

Чтобы сделать это временный, отключите самый верхний сразу после:

def raise_above_all(window):
    window.attributes('-topmost', 1)
    window.attributes('-topmost', 0)

Просто передайте окно, которое вы хотите вызвать в качестве аргумента, и это должно сработать.

Другие советы

Если вы делаете это на Mac, используйте AppleEvents, чтобы сфокусироваться на Python.Например:

import os

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

Добавьте следующие строки перед mainloop():

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

У меня это работает идеально.Это выводит окно на передний план при создании окна, и оно не всегда будет находиться на переднем плане.

Что касается Mac, я заметил, что может возникнуть проблема в том, что если запущено несколько графических интерфейсов python, каждый процесс будет называться "Python", а AppleScript будет стремиться вывести неправильный на передний план.Вот мое решение.Идея состоит в том, чтобы получить список идентификаторов запущенных процессов до и после загрузки Tkinter.(Обратите внимание, что это идентификаторы процессов AppleScript, которые, похоже, не имеют никакого отношения к своим аналогам posix.Поди разберись.) Тогда лишний человек будет твоим, и ты поставишь его на первое место.(Я не думал, что этот цикл в конце будет необходим, но если вы просто получаете каждый процесс с идентификатором 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''')

В 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()

Что-то вроде комбинации различных других методов, это работает на 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()

На 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, окно приложения остается позади.

Мое решение работает во всех случаях, с которыми я столкнулся.

Есть подсказка о том, как заставить окно 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.

Если окно, над которым вы хотели бы поднять свое целевое окно, известно, вы могли бы просто использовать tkraise метод с помощью aboveThis параметр, установленный для окна, которое вы хотите нарисовать поверх.

from tkinter import Tk, ttk, Toplevel

class App(Tk):

    def __init__(self):
        Tk.__init__(self)
        self.title('Main Window')
        self.state('zoomed')
        self.l1 = ttk.Label(self, text='Hello World!')
        self.l1.pack()

        self.s = Splash()
        self.s.tkraise(aboveThis=self)

class Splash(Toplevel):
    def __init__(self):
        Toplevel.__init__(self)
        self.title('Splash Screen')
        self.lift()


app = App()
app.mainloop()
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top