こういうもの。ひとまずWindows限定です。
Tkinterで透明かつ背後のウィンドウにクリックイベントが流れないウィンドウを作って座標を取るの、意外とたいへんでした。 pic.twitter.com/4VBtPKRt9g
— メイユール (@u1F992) May 8, 2023
透明なウィンドウを作る
tk.Tk#wm_attributes
で-transparentcolor
を設定し、ウィンドウ上の特定の色を透明にすることができます。近い色も透過してくれるような器用なものではなくて、完全一致した色だけを抜きます。全面を指定した色のtk.Frameで覆うことで、ウィンドウ枠だけを表示して背後のアプリケーションに重ねること自体は簡単にできます。
import tkinter as tk
root = tk.Tk()
root.geometry("640x480")
root.wm_attributes("-transparentcolor", "white")
tk.Frame(root, background="white").pack(expand=True, fill=tk.BOTH)
root.mainloop()
しかし、試せばわかるように、この方法ではウィンドウ内をクリックするとその操作は背後のウィンドウに流れてフォーカスも外れてしまいます。まるでウィンドウに穴が開いてしまったようです。これでは、背後のアプリケーションに重ねて表示させてクリックした座標で何らかの操作をするような用途には使用できません。
透明なウィンドウで穴を埋める
見えないウィンドウを重ねて表示することで、この穴を埋めることを考えます。
import tkinter as tk
root = tk.Tk()
root.geometry("640x480")
root.wm_attributes("-transparentcolor", "white")
tk.Frame(root, background="white").pack(expand=True, fill=tk.BOTH)
filler = tk.Toplevel(root) # 別ウィンドウを作成
filler.overrideredirect(True) # ウィンドウ枠を削除
filler.transient(root) # タスクバーから消す
filler.wm_attributes("-alpha", 0.0019607843138) # ウィンドウを透明にする。0にすると完全に透明になるが、クリックが背後に流れてしまう。
# 変更されるたびにサイズと位置をrootに合わせて、rootの背後に置く
def on_configure_let_filler_track(_):
filler.geometry(f"{root.winfo_width()}x{root.winfo_height()}+{root.winfo_rootx()}+{root.winfo_rooty()}")
filler.lower(root)
root.bind("<Configure>", on_configure_let_filler_track)
root.mainloop()
透明度を操作する-alpha
ではウィンドウ枠ごと透過してしまうので希望する用途には適していませんが、穴を埋めるためにウィンドウ枠を消した状態で使用しています。試しにfiller.overrideredirect(False)
filler.wm_attributes("-alpha", 0.5)
などとすれば、何をしているのかがわかりやすくなるはずです。
タイトルバー以外の箇所でリサイズができなくなるのは仕様です。また、rootではなくfillerにクリック時のコールバック関数をバインドする必要があることに注意してください。