1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Tkinterで透明なウィンドウを作り、クリックは背後のウィンドウに流さない

Last updated at Posted at 2023-05-08

こういうもの。ひとまずWindows限定です。

透明なウィンドウを作る

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()
追記:0.0019607843138について

この設定値は二分探索で見つけましたが、詳しく考えると1/510=1/(2*255)=0.00196078431373...のことでしょう。ウィンドウのアルファ値が8ビット整数で扱われていると仮定して、Tkinterでの変換処理が以下のように扱われていると推測します。

BYTE alpha_byte = (BYTE)(alpha_float * 255 + 0.5);
// +0.5は四捨五入を表現する慣用的な手法

このとき、alpha_byteが1になる条件は以下のようになります。

alpha_float * 255 + 0.5 = 1
→alpha_float * 255 = 0.5
→alpha_float = 0.5 / 255
→alpha_float = 1 / 510

透明度を操作する-alphaではウィンドウ枠ごと透過してしまうので希望する用途には適していませんが、穴を埋めるためにウィンドウ枠を消した状態で使用しています。試しにfiller.overrideredirect(False) filler.wm_attributes("-alpha", 0.5)などとすれば、何をしているのかがわかりやすくなるはずです。

image.png

タイトルバー以外の箇所でリサイズができなくなるのは仕様です。また、rootではなくfillerにクリック時のコールバック関数をバインドする必要があることに注意してください。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?