2013-01-10 12 views
12

मैं पाइथन के लिए बिल्कुल नया हूं। मैं एक TKinter एंट्री विजेट में फ़ाइल नाम (पूर्ण पथ से पूर्ण) इनपुट करने की कोशिश कर रहा हूं। चूंकि फ़ाइल नाम का पथ बहुत लंबा हो सकता है, इसलिए मैं विंडोज एक्सप्लोरर से सीधे फ़ाइल को खींच और छोड़ने में सक्षम होना चाहता हूं। पर्ल में मैंने निम्नलिखित देखा है:पायथन ड्रैग और ड्रॉप एक्सप्लोरर फाइलों को टिंकर एंट्री विजेट

use Tk::DropSite; 
. 
. 
my $mw = new MainWindow; 
$top = $mw->Toplevel; 
$label_entry = $top->Entry(-width => '45',. -background => 'ivory2')->pack(); 
$label_entry->DropSite(-dropcommand => \&drop,-droptypes => 'Win32',); 

क्या पाइथन में टीकिंटर का उपयोग करके मैं ऐसा कुछ कर सकता हूं?

+0

वास्तव में, 'Tkdnd' मॉड्यूल नहीं है लेकिन यह केवल एप्लिकेशन के अंदर काम करता है (यानी, एप्लिकेशन द्वारा बनाई गई विंडो में खींचें और छोड़ें)। एक विस्तार विस्तार है जिसे TkDND (http://sourceforge.net/projects/tkdnd/) कहा जाता है जो आप चाहते हैं कि इसका समर्थन करता है, इसके लिए पाइथन बाध्यकारी बनाना (यदि कोई नहीं है) आसान होना चाहिए। – mmgp

उत्तर

12

के पास इसे संभालने के लिए कोई आदेश नहीं है, और पाइथन में ड्रैग & ड्रॉप-इंटर-एप्लिकेशन करने के लिए कोई अतिरिक्त अतिरिक्त एक्सटेंशन शामिल नहीं है, इसलिए आपको ऑपरेशन करने के लिए एक एक्सटेंशन की आवश्यकता है। Tkdnd (http://sourceforge.net/projects/tkdnd पर विस्तार, Tkdnd.py मॉड्यूल नहीं) मेरे लिए काम करता है। इसे पायथन से उपयोग करने के लिए, एक रैपर की आवश्यकता होती है। एक के लिए जल्दी खोज रहे हैं, ऐसा लगता है कि http://mail.python.org/pipermail/tkinter-discuss/2005-July/000476.html में ऐसा कोड है। मैंने एक और किया क्योंकि मुझे वह दूसरा पसंद नहीं आया। मेरे रैपर के साथ समस्या यह है कि यह बेहद अवांछित है, वास्तव में मैंने केवल bindtarget फ़ंक्शन का उपयोग किया और केवल 10 सेकंड या उससे भी अधिक के लिए।

नीचे रैपर के साथ, आप कुछ विजेट बना सकते हैं और घोषणा कर सकते हैं कि यह ड्रैग की गई फ़ाइलों को प्राप्त करने का समर्थन करता है।

# The next two lines are not necessary if you installed TkDnd 
# in a proper place. 
import os 
os.environ['TKDND_LIBRARY'] = DIRECTORYTOTHETKDNDBINARY 

import Tkinter 
from untested_tkdnd_wrapper import TkDND 

root = Tkinter.Tk() 

dnd = TkDND(root) 

entry = Tkinter.Entry() 
entry.pack() 

def handle(event): 
    event.widget.insert(0, event.data) 

dnd.bindtarget(entry, handle, 'text/uri-list') 

root.mainloop() 

यहाँ और untested_tkdnd_wrapper.py के लिए कोड है:: यहाँ एक उदाहरण है

import os 
import Tkinter 

def _load_tkdnd(master): 
    tkdndlib = os.environ.get('TKDND_LIBRARY') 
    if tkdndlib: 
     master.tk.eval('global auto_path; lappend auto_path {%s}' % tkdndlib) 
    master.tk.eval('package require tkdnd') 
    master._tkdnd_loaded = True 


class TkDND(object): 
    def __init__(self, master): 
     if not getattr(master, '_tkdnd_loaded', False): 
      _load_tkdnd(master) 
     self.master = master 
     self.tk = master.tk 

    # Available pre-defined values for the 'dndtype' parameter: 
    # text/plain 
    # text/plain;charset=UTF-8 
    # text/uri-list 

    def bindtarget(self, window, callback, dndtype, event='<Drop>', priority=50): 
     cmd = self._prepare_tkdnd_func(callback) 
     return self.tk.call('dnd', 'bindtarget', window, dndtype, event, 
       cmd, priority) 

    def bindtarget_query(self, window, dndtype=None, event='<Drop>'): 
     return self.tk.call('dnd', 'bindtarget', window, dndtype, event) 

    def cleartarget(self, window): 
     self.tk.call('dnd', 'cleartarget', window) 


    def bindsource(self, window, callback, dndtype, priority=50): 
     cmd = self._prepare_tkdnd_func(callback) 
     self.tk.call('dnd', 'bindsource', window, dndtype, cmd, priority) 

    def bindsource_query(self, window, dndtype=None): 
     return self.tk.call('dnd', 'bindsource', window, dndtype) 

    def clearsource(self, window): 
     self.tk.call('dnd', 'clearsource', window) 


    def drag(self, window, actions=None, descriptions=None, 
      cursorwin=None, callback=None): 
     cmd = None 
     if cursorwin is not None: 
      if callback is not None: 
       cmd = self._prepare_tkdnd_func(callback) 
     self.tk.call('dnd', 'drag', window, actions, descriptions, 
       cursorwin, cmd) 


    _subst_format = ('%A', '%a', '%b', '%D', '%d', '%m', '%T', 
      '%W', '%X', '%Y', '%x', '%y') 
    _subst_format_str = " ".join(_subst_format) 

    def _prepare_tkdnd_func(self, callback): 
     funcid = self.master.register(callback, self._dndsubstitute) 
     cmd = ('%s %s' % (funcid, self._subst_format_str)) 
     return cmd 

    def _dndsubstitute(self, *args): 
     if len(args) != len(self._subst_format): 
      return args 

     def try_int(x): 
      x = str(x) 
      try: 
       return int(x) 
      except ValueError: 
       return x 

     A, a, b, D, d, m, T, W, X, Y, x, y = args 

     event = Tkinter.Event() 
     event.action = A  # Current action of the drag and drop operation. 
     event.action_list = a # Action list supported by the drag source. 
     event.mouse_button = b # Mouse button pressed during the drag and drop. 
     event.data = D   # The data that has been dropped. 
     event.descr = d  # The list of descriptions. 
     event.modifier = m  # The list of modifier keyboard keys pressed. 
     event.dndtype = T 
     event.widget = self.master.nametowidget(W) 
     event.x_root = X  # Mouse pointer x coord, relative to the root win. 
     event.y_root = Y 
     event.x = x   # Mouse pointer x coord, relative to the widget. 
     event.y = y 

     event.action_list = str(event.action_list).split() 
     for name in ('mouse_button', 'x', 'y', 'x_root', 'y_root'): 
      setattr(event, name, try_int(getattr(event, name))) 

     return (event,) 

Tkdnd के साथ, आप एक tkdnd.tcl प्रोग्राम है जो खुद सी विस्तार यह प्रदान करता है से अधिक एक उच्च स्तर है मिल जाएगा। मैंने इस उच्च स्तर के कोड को लपेट नहीं लिया है, लेकिन यह निचले स्तर के आवरण का उपयोग करने के बजाय पायथन में इसे दोहराने के लिए और अधिक दिलचस्प हो सकता है।

+0

उस @mmgp के लिए बहुत धन्यवाद! बस यह ध्यान रखना चाहता था कि 'tkDND' ऐसा लगता है कि एक विजेट को बाध्य करने में सक्षम नहीं है जिसमें मास्टर/पैरेंट' रूट 'के अलावा कोई अन्य है (_ मैंने स्क्रिप्ट में अपनी कुछ समस्याओं का उल्लेख किया है [यूट्यूब-डीएल-गुई -tkdnd.py] (http://sdaaubckp.svn.sourceforge.net/viewvc/sdaaubckp/xtra/youtube-dl-gui-tkdnd/youtube-dl-gui-tkdnd.py?view=markup) _)। बहुत धन्यवाद फिर - चीयर्स! – sdaau

+1

@sdaau मैंने अभी एक विजेट बनाया है: 'main = ttk.frame(); प्रविष्टि = ttk.Entry (मुख्य) '। और मैं 'bindtarget 'चलाता हूं' प्रविष्टि 'पर ठीक है, और यह ड्रॉप घटनाओं को स्वीकार करता है। क्या आप सुनिश्चित हैं कि समस्या कहीं और नहीं है? क्या आप एक न्यूनतम उदाहरण दिखा सकते हैं जो विफल रहता है? – mmgp

3

इस प्रश्न को मूल रूप से पोस्ट किए जाने के बाद से चीजें प्रगति हुई हैं, और tkdnd2.8 (Tcl एक्सटेंशन) और TkinterDnD2 (tkdnd2.8 के लिए पायथन रैपर) SourceForge.net पर आसानी से उपलब्ध हैं।

यहां जो कुछ भी आपने पूछा है, वह करने के लिए यहां न्यूनतम नमूना कोड है।

import Tkinter 
from TkinterDnD2 import * 

def drop(event): 
    entry_sv.set(event.data) 

root = TkinterDnD.Tk() 
entry_sv = Tkinter.StringVar() 
entry = Tkinter.Entry(root, textvar=entry_sv, width=80) 
entry.pack(fill=Tkinter.X) 
entry.drop_target_register(DND_FILES) 
entry.dnd_bind('<<Drop>>', drop) 
root.mainloop() 

आप अजगर 2.7 और 3.6 पर डाउनलोड और विंडोज और मैक दोनों के लिए स्थापना की जानकारी के लिए How to Install and Use TkDnD with Python 2.7 Tkinter on OSX देख सकते हैं।

संबंधित मुद्दे