Python tkinter GUI プログラミング ドラッグ・アンド・ドロップ

 今日も見に来てくださって、ありがとうございます。石川さんです。

 先日、tkinterモジュールのソースコードを眺めていたら、dnd.pyというファイルがありましてちょっと、おお、と思ったので記録しておきます。dndというからにはドラッグ・アンド・ドロップでしょ。

動作確認

 ぼくは、Anacondaを使っているので、C:\ProgramData\Anaconda3\Lib\tkinterにモジュールがあって、そこにこのdnd.pyファイルがあります。ソースを見ると、最後の方にありました、テスト用に直接実行できるコードです。

if __name__ == '__main__':
    test()

 さっそく実行してみました。

Dndテスト結果

ソースコード

 ソースコードを追加したかったのですが、みなさんのフォルダにもあるはずなのと、(ぼくの環境は、C:\ProgramData\Anaconda3\Lib\tkinter\dnd.pyです。)、著作権的にも問題があると思いますので、今回はそちらをご覧ください。

解説

 ソースコードは下から見ていくとよさそうですね。まずは、ルートのTkをインスタンス化してから、その後、Testerクラスを使ってウィンドウを三つ作成しています。この中にはそれぞれCanvasが作られてありますね。そして、次にIconクラスのインスタンスを三つ作って、それぞれそのウィンドウのCanvasattachを実行する、という流れですね。attachでは、引数で受け取ったCanvasLabelをつくって、それからマウスの第一ボタンが押されたときの処理としてpressが登録されています。

 pressでは、dndモジュールの最初に定義されているdnd_startが呼び出されていて、ここでDndHandlerによってラップされたインスタンスが作成されます。DndHandlerの初期化の処理で、マウスのボタンがリリースされたときのイベントの処理にon_releaseが登録され、<Motion>イベントの処理にon_motionが登録されています。要するにマウスが動くたびにon_motionが呼び出されて、マウスのボタンを離したときにon_releaseが呼び出されるようにしました、ということですね。あ、あと、カーソルが"hand2"に変更されているように見えます。

 このマウスが動くたびに呼び出されるon_motionは、処理中にターゲットのCanvasが変更されていない間はdnd_motionを呼び出すことでキャンバス内のラベルを移動させています。ターゲットのCanvasが変更されたときは、dnd_leavednd_enterがそれぞれ変更前のCanvasと変更後のCanvasで呼び出されて、ドラッグ・アンド・ドロップ実現しています。

 最後にマウスのボタンが離されたときに、イベントが削除されたりカーソルを元に戻したりしたあとに、dnd_commitを呼び出して終了処理をしています。

まとめ

 ドラッグアンドドロップは、実装するのに、こんなに複雑なことをしないといけないのですねぇ。今回はざっと眺めただけなのでよいですけど、自分で同じ機能を実現するのは、かなり苦労しそうです。

“Python tkinter GUI プログラミング ドラッグ・アンド・ドロップ” への1件の返信

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です


reCaptcha の認証期間が終了しました。ページを再読み込みしてください。