Tkinterアプリケーションを手前に表示するにはどうすればよいですか?現在、ウィンドウは他のすべてのウィンドウの背後に表示され、フォーカスがありません。
呼び出す必要のあるメソッドはありますか?
「他のウィンドウ」と言うときにアプリケーションウィンドウを意味すると仮定すると、トップレベルまたは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)
引数として発生させたいウィンドウを渡すだけで、これは機能するはずです。
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 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''')
他のさまざまな方法の組み合わせで、これは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()
_
Mac OS Xでは、PyObjCはosascriptへのシェルアウトよりもクリーンでエラーの少ない方法を提供します。
import os
from Cocoa import NSRunningApplication, NSApplicationActivateIgnoringOtherApps
app = NSRunningApplication.runningApplicationWithProcessIdentifier_(os.getpid())
app.activateWithOptions_(NSApplicationActivateIgnoringOtherApps)
最近、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()
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からスクリプトを直接実行すると、アプリウィンドウが遅れます。
私のソリューションは、私が遭遇したすべてのケースで機能します。