前提・実現したいこと
環境:
OS:Linux Mint 20
Python:3.8
Tk&Tcl:8.6
TkDND:2.6
発生している問題・エラーメッセージ
tkinterの通常ウィジェットにはドロップできるのですが、
ttkのウィジェットにドロップできません。
該当のソースコード
以下のようなファイル配置です:
/ |-tkdnd.py |-dnd_test_tkinter.py --dnd_test_ttk.py
tkdnd.py(こちらで配布されている最新版の改変版(のコメント削除版))
python3
1# -*- coding: utf-8 -*- 2 3try: 4 import Tkinter as tkinter 5 import Tix as tix 6 import ttk 7except ImportError: 8 import tkinter 9 from tkinter import tix 10 from tkinter import ttk 11import os 12TkdndVersion = None 13# dnd actions 14PRIVATE = 'private' 15NONE = 'none' 16ASK = 'ask' 17COPY = 'copy' 18MOVE = 'move' 19LINK = 'link' 20REFUSE_DROP = 'refuse_drop' 21# dnd types 22DND_TEXT = 'DND_Text' 23DND_FILES = 'DND_Files' 24DND_ALL = '*' 25CF_UNICODETEXT = 'CF_UNICODETEXT' 26CF_TEXT = 'CF_TEXT' 27CF_HDROP = 'CF_HDROP' 28FileGroupDescriptor = 'FileGroupDescriptor - FileContents'# ?? 29FileGroupDescriptorW = 'FileGroupDescriptorW - FileContents'# ?? 30 31def _require(tkroot): 32 '''Internal function.''' 33 global TkdndVersion 34 tkdndlib = os.environ.get('TKDND_LIBRARY') 35 if tkdndlib != "__null__": 36 if tkdndlib: 37 tkroot.tk.eval('global auto_path; lappend auto_path {%s}' % tkdndlib) 38 try: 39 TkdndVersion = tkroot.tk.call('package', 'require', 'tkdnd') 40 except tkinter.TclError: 41 raise RuntimeError('Unable to load tkdnd library.') 42 return TkdndVersion 43 44class DnDEvent: 45 pass 46 47class DnDWrapper: 48 _subst_format_dnd = ('%A', '%a', '%b', '%C', '%c', '{%CST}', 49 '{%CTT}', '%D', '%e', '{%L}', '{%m}', '{%ST}', 50 '%T', '{%t}', '{%TT}', '%W', '%X', '%Y') 51 _subst_format_str_dnd = " ".join(_subst_format_dnd) 52 tkinter.BaseWidget._subst_format_dnd = _subst_format_dnd 53 tkinter.BaseWidget._subst_format_str_dnd = _subst_format_str_dnd 54 55 def _substitute_dnd(self, *args): 56 if len(args) != len(self._subst_format_dnd): 57 return args 58 def getint_event(s): 59 try: 60 return int(s) 61 except ValueError: 62 return s 63 def splitlist_event(s): 64 try: 65 return self.tk.splitlist(s) 66 except ValueError: 67 return s 68 69 A, a, b, C, c, CST, CTT, D, e, L, m, ST, T, t, TT, W, X, Y = args 70 ev = DnDEvent() 71 ev.action = A 72 ev.actions = splitlist_event(a) 73 ev.button = getint_event(b) 74 ev.code = C 75 ev.codes = splitlist_event(c) 76 ev.commonsourcetypes = splitlist_event(CST) 77 ev.commontargettypes = splitlist_event(CTT) 78 ev.data = D 79 ev.name = e 80 ev.types = splitlist_event(L) 81 ev.modifiers = splitlist_event(m) 82 ev.supportedsourcetypes = splitlist_event(ST) 83 ev.sourcetypes = splitlist_event(t) 84 ev.type = T 85 ev.supportedtargettypes = splitlist_event(TT) 86 try: 87 ev.widget = self.nametowidget(W) 88 except KeyError: 89 ev.widget = W 90 ev.x_root = getint_event(X) 91 ev.y_root = getint_event(Y) 92 return (ev,) 93 tkinter.BaseWidget._substitute_dnd = _substitute_dnd 94 95 def _dnd_bind(self, what, sequence, func, add, needcleanup=True): 96 if isinstance(func, str): 97 self.tk.call(what + (sequence, func)) 98 elif func: 99 funcid = self._register(func, self._substitute_dnd, needcleanup) 100 # FIXME: why doesn't the "return 'break'" mechanism work here?? 101 #cmd = ('%sif {"[%s %s]" == "break"} break\n' % (add and '+' or '', 102 # funcid, self._subst_format_str_dnd)) 103 cmd = '%s%s %s' %(add and '+' or '', funcid, 104 self._subst_format_str_dnd) 105 self.tk.call(what + (sequence, cmd)) 106 return funcid 107 elif sequence: 108 return self.tk.call(what + (sequence,)) 109 else: 110 return self.tk.splitlist(self.tk.call(what)) 111 tkinter.BaseWidget._dnd_bind = _dnd_bind 112 113 def dnd_bind(self, sequence=None, func=None, add=None): 114 return self._dnd_bind(('bind', self._w), sequence, func, add) 115 tkinter.BaseWidget.dnd_bind = dnd_bind 116 117 def drag_source_register(self, button=None, *dndtypes): 118 if button is None: 119 button = 1 120 else: 121 try: 122 button = int(button) 123 except ValueError: 124 # no button defined, button is actually 125 # something like DND_TEXT 126 dndtypes = (button,) + dndtypes 127 button = 1 128 self.tk.call( 129 'tkdnd::drag_source', 'register', self._w, dndtypes, button) 130 tkinter.BaseWidget.drag_source_register = drag_source_register 131 132 def drag_source_unregister(self): 133 self.tk.call('tkdnd::drag_source', 'unregister', self._w) 134 tkinter.BaseWidget.drag_source_unregister = drag_source_unregister 135 136 def drop_target_register(self, *dndtypes): 137 self.tk.call('tkdnd::drop_target', 'register', self._w, dndtypes) 138 tkinter.BaseWidget.drop_target_register = drop_target_register 139 140 def drop_target_unregister(self): 141 self.tk.call('tkdnd::drop_target', 'unregister', self._w) 142 tkinter.BaseWidget.drop_target_unregister = drop_target_unregister 143 144 def platform_independent_types(self, *dndtypes): 145 return self.tk.split(self.tk.call( 146 'tkdnd::platform_independent_types', dndtypes)) 147 tkinter.BaseWidget.platform_independent_types = platform_independent_types 148 149 def platform_specific_types(self, *dndtypes): 150 return self.tk.split(self.tk.call( 151 'tkdnd::platform_specific_types', dndtypes)) 152 tkinter.BaseWidget.platform_specific_types = platform_specific_types 153 154 def get_dropfile_tempdir(self): 155 return self.tk.call('tkdnd::GetDropFileTempDirectory') 156 tkinter.BaseWidget.get_dropfile_tempdir = get_dropfile_tempdir 157 158 def set_dropfile_tempdir(self, tempdir): 159 self.tk.call('tkdnd::SetDropFileTempDirectory', tempdir) 160 tkinter.BaseWidget.set_dropfile_tempdir = set_dropfile_tempdir 161 162class Tk(tkinter.Tk, DnDWrapper): 163 def __init__(self, *args, **kw): 164 tkinter.Tk.__init__(self, *args, **kw) 165 self.TkdndVersion = _require(self) 166 167class TixTk(tix.Tk, DnDWrapper): 168 def __init__(self, *args, **kw): 169 tix.Tk.__init__(self, *args, **kw) 170 self.TkdndVersion = _require(self)
ttkバージョン(dnd_test_ttk.py - 今回問題が発生しているものです。)
python3
1from tkdnd import * 2from tkinter import ttk 3 4root = Tk()#ウィンドウ 5 6frame = ttk.Frame(root, width=100, height=100)#ドロップされるフレーム 7frame.pack(fill="both",expand=True) 8 9frame.drop_target_register(DND_FILES, DND_TEXT)#対応させるドロップフォーマット 10frame.dnd_bind('<<Drop>>', lambda event:print(event.data))#イベントのバインド 11 12root.mainloop()
tkinterバージョン(dnd_test_tkinter.py)
python3
1from tkinter import * 2import tkinter 3 4root = Tk()#ウィンドウ 5 6frame = tkinter.Frame(root, width=100, height=100)#ドロップされるフレーム 7frame.pack(fill="both",expand=True) 8 9frame.drop_target_register(DND_FILES, DND_TEXT)#対応させるドロップフォーマット 10frame.dnd_bind('<<Drop>>', lambda event:print(event.data))#イベントのバインド 11 12root.mainloop()
試したこと
順序の入れ替えなど
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/07/18 06:04 編集
2020/07/18 11:28
2020/07/19 16:37 編集
2020/07/20 00:14 編集
2020/07/20 14:50
2020/07/21 05:43 編集
2020/07/23 11:45 編集