FC2ブログ

Anaconda 学習:GUI アプリ開発は Tkinter で?

2018-04-18 :  PCクリニック
先日(2018-04-11)の記事「kivy 学習:Kv ファイルを別途用意しない方法」で、

更なる、学習をしていたが、・・・・・


どうも、「kivy」についてはまだまだ学習が必要ダ。

なので、
昔の「Tkinter」に戻ってみた。
参照記事:「Tkinter:ドラッグ&ドロップ対応法


しかし、問題が1つあった。

今後使う Python は、Anaconda で しかも 64bit 版


これは簡単に、行けるのか?

「Python GUI ドラッグ&ドロップ」検索で、
1つ見つけた:
TkinterでDnDを実装するには(64bit Window版)

  TkinterでエクスプローラからDnDでファイルを受け取るアプリを作成
  してみようと思いました。

  参考サイトの内容を元にコードを作成してみましたが、残念なことに
  64bit Windows 10 ではうまく動作しません。

  Python+TkでD&D -MasaHeroの日記より
  http://d.hatena.ne.jp/MasaHero/20111201/p1

  ctypesを使って、WindowsのDDLを直接操作しています。
  32bit Windows7 にて、python 2.7 と 3.4で動作を確認しています。

  これを64bit Windowsでも動作させるにはどのように修正すればよいでしょうか?


これで学習して、
<紙>流コードを作った:
# -*- coding: utf-8 -*-

import Tkinter as tk
import ctypes, sys
from ctypes import c_long, WINFUNCTYPE
from ctypes.wintypes import HWND, UINT, WPARAM, LPARAM

WM_DROPFILES = 0x0233
GWL_WNDPROC = -4
FS_ENCODING = sys.getfilesystemencoding()
DragAcceptFiles = ctypes.windll.shell32.DragAcceptFiles
DragQueryFile = ctypes.windll.shell32.DragQueryFile
DragQueryFile.argtypes = [ ctypes.c_void_p, UINT, ctypes.c_void_p, UINT ]
DragFinish = ctypes.windll.shell32.DragFinish
DragFinish.argtypes = [ ctypes.c_void_p ]
CallWindowProc = ctypes.windll.user32.CallWindowProcW
CallWindowProc.argtypes = [ ctypes.c_void_p, HWND , UINT, WPARAM, LPARAM ]
try: SetWindowLong = ctypes.windll.user32.SetWindowLongPtrW
except AttributeError: SetWindowLong = ctypes.windll.user32.SetWindowLongW

class TkApp(tk.Frame):
dnd_interval = 600

def __init__(self, *args, **kargs):
tk.Frame.__init__(self, *args, **kargs)
self.createwidget()
self.dropnames = []
win = args[0] if args else self._root()
win = self.tw

def drop_check():
if self.dropnames:
fns = self.dropnames
self.dropnames = []
self.dnd_notify(fns)
win.after(self.dnd_interval, drop_check)

@WINFUNCTYPE(c_long, HWND, UINT, WPARAM, LPARAM)
def replace_win_proc(hwnd, msg, wp, lp):
u"""D&D用のコールバック
ファイルのドラッグアンドドロップイベント(WM_DROPFILES)を検出して、
ドロップされたファイル名を保持する。
ここでウィンドウ(tk)を使用するとハングアップするのでデータ保存だけ行う。
"""
if msg == WM_DROPFILES:
nf = DragQueryFile(wp, -1, None, 0)
buf = ctypes.c_buffer(260)
fns = [ buf.value.decode(FS_ENCODING) for nn in range(nf) \
if DragQueryFile(wp, nn , buf, ctypes.sizeof(buf)) ]
DragFinish(wp)
self.dropnames.extend(fns)
print("%s dnd_notify: %s" % (self, hwnd))
return CallWindowProc(self.org_proc, hwnd, msg, wp, lp)

def dnd_setup():
"Windowsのイベント処理のフックを定義する"
hwnd = win.winfo_id()
DragAcceptFiles(hwnd, True)

self.win_proc = replace_win_proc
self.org_proc = SetWindowLong(hwnd, GWL_WNDPROC, self.win_proc)

win.after_idle(drop_check)
print("%s dnd_setup: %s,%s" % (self, hwnd, self.org_proc))

self.pack(fill='both', expand=1)
win.after_idle(dnd_setup)

def createwidget(self):
tw = tk.Text(self, width=30,height=16)
tw.pack(fill='both', expand=1)
self.tw = tw

def dnd_notify(self, filenames):
for nn in filenames:
self.tw.insert('end',"%s\n" % nn)

if __name__ == "__main__":
a = TkApp()
if 0: TkApp(tk.Toplevel()) # 複数ウィンドウに対応
a.mainloop()
これで動いた。


よく分からないが、
これで行こうかナ?



本日はここまで。


Anaconda ( Python ) 学習は続く。


見ていただいた序でとは厚かましい限りですが、
お帰りに投票して頂けるとなお嬉しいです。 ⇒ blogram投票ボタン


180311
関連記事
スポンサーサイト

コメントの投稿

管理者にだけ表示を許可する

おきてがみ/blogram
blogram投票ボタン



おきてがみ

最新記事
カレンダー
07 | 2018/08 | 09
- - - 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31 -
月別アーカイブ
カテゴリ
最新コメント
検索フォーム
リンク
プロフィール

<紙>

Author:<紙>
ようこそ。
「パソコンヲタクの雑記帳」
もろもろなことを綴っています。
パソコン ヲタクってねくら?
画像は kami でなく kani です。

カウンター(fc2、i2i) /Google Analytics


i2i(from 2010-08-24)
Total =
Today  =  
Yesterday=
アンチエイジング

Google Analytics
ブックマーク