web-dev-qa-db-ja.com

Tkinterウィンドウを前面にジャンプさせる方法は?

Tkinterアプリケーションを手前に表示するにはどうすればよいですか?現在、ウィンドウは他のすべてのウィンドウの背後に表示され、フォーカスがありません。

呼び出す必要のあるメソッドはありますか?

48
nathan

「他のウィンドウ」と言うときにアプリケーションウィンドウを意味すると仮定すると、トップレベルまたはTkでlift()メソッドを使用できます。

root.lift()

ウィンドウを他のすべてのウィンドウの上に維持する場合は、次を使用します。

root.attributes("-topmost", True)

rootはトップレベルまたはTkです。 -の前にある"topmost"を忘れないでください!

temporaryにするには、直後の一番上を無効にします:

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

引数として発生させたいウィンドウを渡すだけで、これは機能するはずです。

63
D K

Macでこれを行う場合は、AppleEventsを使用してPythonに焦点を当てます。例えば:

import os

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

Mainloop()の前に次の行を追加します。

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

それは私にとって完璧に機能します。ウィンドウが生成されると、ウィンドウが前面に表示され、常に前面に表示されるわけではありません。

29
user6107173

Macに関しては、複数のpython GUIが実行されている場合、すべてのプロセスの名前が「Python」になり、AppleScriptが間違ったプロセスを前面に表示する傾向があるという問題があることに気付きました。ここに私の解決策があります。アイデアは、Tkinterをロードする前後に実行中のプロセスIDのリストを取得することです(これらは、対応するposixとは無関係のAppleScriptプロセスIDであることに注意してください。 outはあなたのものになり、それを最前面に移動します(最後のループが必要になるとは思いませんでしたが、IDがprocIDであるすべてのプロセスを取得すると、AppleScriptは名前で識別される1つのオブジェクトを返すようです。もちろん、それは一意ではない「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''')
5
Ted C

他のさまざまな方法の組み合わせで、これはOS X 10.11で動作し、Python 3.5.1 venvで実行され、他のプラットフォームでも動作するはずです。また、プロセスごとにアプリをターゲットにします。アプリ名ではなくid。

_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()
_
4
Caleb Hattingh

Mac OS Xでは、PyObjCはosascriptへのシェルアウトよりもクリーンでエラーの少ない方法を提供します。

import os
from Cocoa import NSRunningApplication, NSApplicationActivateIgnoringOtherApps

app = NSRunningApplication.runningApplicationWithProcessIdentifier_(os.getpid())
app.activateWithOptions_(NSApplicationActivateIgnoringOtherApps)
4
MagerValp

最近、Macでも同じ質問がありました。 Macでは@MagerValp、その他のシステムでは@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()
4
Tomasz Nguyen

MacOS High Sierra、py3.6.4でのソリューションは次のとおりです。

_def OnFocusIn(event):
    if type(event.widget).__== '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()を試しました。それらはすべて1つのケースで失敗します。PyCharmのようにIDEからスクリプトを直接実行すると、アプリウィンドウが遅れます。

私のソリューションは、私が遭遇したすべてのケースで機能します。

0
kakyo