Tkinterアプリケーションを前面にジャンプさせるにはどうすればよいですか?現在、ウィンドウは他のすべてのウィンドウの後ろに表示され、フォーカスを取得しません。
呼び出すべきメソッドはありますか?
「他のウィンドウ」と言うときにアプリケーションウィンドウを意味すると仮定するとlift()、トップレベルまたはTkでこのメソッドを使用できます。
root.lift()
ウィンドウを他のすべてのウィンドウの上に配置したい場合は、次を使用します。
root.attributes("-topmost", True)
rootトップレベルまたは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 GUIが実行されている場合、すべてのプロセスに「Python」という名前が付けられ、AppleScriptが間違ったものを前面にプロモートする傾向があるという問題があることに気付きました。これが私の解決策です。アイデアは、Tkinterをロードする前後に実行中のプロセスIDのリストを取得することです。(これらはAppleScriptプロセスIDであり、対応するposixとは関係がないように見えることに注意してください。図を参照してください。)次に、奇妙な人があなたのものになり、それを最前面に移動します。(最後にループが必要になるとは思いませんでしたが、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''')
Mac OS Xでは、PyObjCは、osascriptにシェルアウトするよりもクリーンでエラーが発生しにくい方法を提供します。
import os
from Cocoa import NSRunningApplication, NSApplicationActivateIgnoringOtherApps
app = NSRunningApplication.runningApplicationWithProcessIdentifier_(os.getpid())
app.activateWithOptions_(NSApplicationActivateIgnoringOtherApps)
最近、Macで同じ質問がありました。@MagerValpMacと@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()
他のさまざまな方法の組み合わせの一部ですが、これはvenvで実行されているOS X10.11およびPython3.5.1で機能し、他のプラットフォームでも機能するはずです。また、アプリ名ではなくプロセス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()
Tkinter._test()関数でmainloop()を呼び出すときに、Tkinterウィンドウにフォーカスを合わせる方法についてのヒントがあります。
# The following three commands are needed so the window pops
# up on top on Windows...
root.iconify()
root.update()
root.deiconify()
root.mainloop()
これは、私がこれを行うために見つけた最もクリーンで最も適切な方法ですが、Windowsシステムにのみ必要です。
この答えは、1つのTkinterウィンドウを他のTkinterウィンドウの上にポップアップさせることです。
私のアプリでは、最初に上に表示さtoplevelれるはるかに小さなウィンドウを呼び出す大きなウィンドウがあります。top2toplevel
ユーザーがウィンドウ内をクリックするtoplevelと、フォーカスが得られ、ウィンドウがドラッグされて外れるtop2まで、はるかに小さいウィンドウが窒息します。toplevel
解決策は、ボタンをクリックしtoplevelて再起動top2することです。top2open関数は、すでに実行されていることを認識しているので、単に上に持ち上げてフォーカスを与えます。
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()。それらはすべて1つのケースで失敗します:PyCharmのようなIDEから直接スクリプトを実行すると、アプリウィンドウは後ろにとどまります。
私の解決策は、私が遭遇したすべての場合に機能します。