2021/12/10(金) [n年前の日記]
#1 [python] tkinterdnd2を試用
Python + tkinter を使うと、ちょっとしたGUIアプリを作ることができるのだけど、tkinter の標準状態ではドラッグアンドロップ(DnD、D&D)を受け付ける機能が無いそうで。例えば、Windows のエクスプローラ等から tkinter のウインドウにファイルアイコンをD&Dしてもファイルパスを取得することができない。
そのあたりどうにかできないのかなとググってみたら、tkinterdnd2 というライブラリをインストールするとできるようになると知ったので、手元で少し試してみた。
環境は Windows10 x64 21H1 + Python 3.9.9 x64。
_【Python】tkinter:ファイルのドラッグアンドドロップ(パス取得、画像表示) | OFFICE54
_Eliav2/tkinterdnd2: Tkinter native drag and drop support for windows, unix and Mac OSX.
_tkinterdnd2 - PyPI
そのあたりどうにかできないのかなとググってみたら、tkinterdnd2 というライブラリをインストールするとできるようになると知ったので、手元で少し試してみた。
環境は Windows10 x64 21H1 + Python 3.9.9 x64。
_【Python】tkinter:ファイルのドラッグアンドドロップ(パス取得、画像表示) | OFFICE54
_Eliav2/tkinterdnd2: Tkinter native drag and drop support for windows, unix and Mac OSX.
_tkinterdnd2 - PyPI
◎ インストール。 :
昔は、tkinterdnd2 を使うためには、TkDND というTkの拡張パッケージを別途インストールする必要があったのだけど。
_mieki256's diary - Python + Tkinter でドラッグアンドドロップ
今現在は、tkinterdnd2 を pip でインストーするだけで使えるようになる模様。github上のファイル群を眺めたら *.dll も並んでいたので、必要な *.dll も pip で入れてくれるのだろう。
今回は tkinterdnd2 0.3.0 がインストールされた。
_mieki256's diary - Python + Tkinter でドラッグアンドドロップ
今現在は、tkinterdnd2 を pip でインストーするだけで使えるようになる模様。github上のファイル群を眺めたら *.dll も並んでいたので、必要な *.dll も pip で入れてくれるのだろう。
pip install tkinterdnd2
今回は tkinterdnd2 0.3.0 がインストールされた。
◎ 動作サンプル。 :
解説記事を参考にしつつ、tk.Entry(InputBox相当、入力フィールド) にファイルをD&Dすれば、ファイルパスが入るスクリプトを書いてみた。
_02_tkintrdnd2_sample2.py
エクスプローラからファイルをD&Dして、ファイルパスを取得できた。
ちなみに、巷の解説記事ではスクリプト内で .dnd_bind("<>", drop) と記述されていたけど、現行バージョンではその記述だと動かなった。.dnd_bind("<<Drop>>", drop) にしてみたら動いてくれた。
_02_tkintrdnd2_sample2.py
import tkinter as tk from tkinter import ttk from tkinterdnd2 import * def drop(event): print(event.data) text.set(event.data) root = TkinterDnD.Tk() root.geometry("640x100") root.title("Drag and drop with Entry") text = tk.StringVar() text.set("Please file drop") entry = ttk.Entry(root, textvariable=text) entry.pack(expand=True, fill=tk.X, padx=16, pady=8) entry.drop_target_register(DND_FILES) entry.dnd_bind("<<Drop>>", drop) root.mainloop()
エクスプローラからファイルをD&Dして、ファイルパスを取得できた。
ちなみに、巷の解説記事ではスクリプト内で .dnd_bind("<>", drop) と記述されていたけど、現行バージョンではその記述だと動かなった。.dnd_bind("<<Drop>>", drop) にしてみたら動いてくれた。
◎ windnd を試用。 :
ググっていたら、windnd というライブラリをインストールすることでもD&Dが使えるようになると知った。
_windnd - PyPI
_cilame/windnd
_Arrastrar y soltar archivo de implementacion de Python + tkinter
github上のソースを眺めてみたけれど、Windows API を使ってD&Dを使えるようにしているっぽい。tkinterdnd2 の場合は動作させるために複数の *.dll をインストールするけれど、windnd は .pyファイル一つで実現している模様。
もちろん、Windows API を使っているから Windows上でしか使えないというデメリットはあるけれど、Windows上でしか使わないスクリプトであれば問題にはならないはず。
試しにインストールしてサンプルを書いてみた。
_01_windnd_sample1.py
こちらも動いてくれた。
_windnd - PyPI
_cilame/windnd
_Arrastrar y soltar archivo de implementacion de Python + tkinter
github上のソースを眺めてみたけれど、Windows API を使ってD&Dを使えるようにしているっぽい。tkinterdnd2 の場合は動作させるために複数の *.dll をインストールするけれど、windnd は .pyファイル一つで実現している模様。
もちろん、Windows API を使っているから Windows上でしか使えないというデメリットはあるけれど、Windows上でしか使わないスクリプトであれば問題にはならないはず。
試しにインストールしてサンプルを書いてみた。
pip install windnd
_01_windnd_sample1.py
import tkinter as tk import windnd def dragged_files(files): s = ";".join((item.decode("utf-8") for item in files)) text.set(s) print(text.get()) root = tk.Tk() text = tk.StringVar() text.set("Please file drop") entry = tk.Entry(root, textvariable=text, width=80) entry.pack(expand=True, fill=tk.X, padx=16, pady=8) windnd.hook_dropfiles(root, func=dragged_files) root.mainloop()
こちらも動いてくれた。
[ ツッコむ ]
以上です。