将资源管理器文件拖放到 tkinter 条目小部件? [英] Drag and drop explorer files to tkinter entry widget?

查看:41
本文介绍了将资源管理器文件拖放到 tkinter 条目小部件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对 Python 还很陌生.我正在尝试向 TKinter 条目小部件输入文件名(完整路径).由于文件名的路径可能很长,我希望能够直接拖放文件从 Windows 资源管理器.在 Perl 中,我看到了以下内容:

I'm fairly new to Python. I'm trying to input a file name (complete with full path) to a TKinter entry widget. Since the path to the file name can be very long I would like to be able to drag and drop the file directly from Windows Explorer. In Perl I have seen the following:

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',);

我可以在 Python 中使用 TKinter 做类似的事情吗?

Is there something similar I can do using TKinter in Python?

推荐答案

Tk 没有任何命令来处理这个问题,而且 Python 不包含任何额外的 Tk 扩展来执行拖拽&删除应用程序间,因此您需要一个扩展来执行操作.Tkdnd(http://sourceforge.net/projects/tkdnd 上的 Tk 扩展,而不是 Tkdnd.py 模块)对我有用.要在 Python 中使用它,需要一个包装器.赶紧找一个,好像http://mail.python.org/pipermail/tkinter-discuss/2005-July/000476.html 包含这样的代码.我做了另一个,因为我不喜欢另一个.我的包装器的问题在于它未经测试,实际上我只使用了 bindtarget 函数,而且只使用了 10 秒左右.

Tk does not have any command to handle that, and Python doesn't include any extra Tk extension to perform drag & drop inter-applications, therefore you need an extension to perform the operation. Tkdnd (the Tk extension at http://sourceforge.net/projects/tkdnd, not the Tkdnd.py module) works for me. To use it from Python, a wrapper is required. Quickly searching for one, it seems http://mail.python.org/pipermail/tkinter-discuss/2005-July/000476.html contains such code. I did another one because I didn't like that other one. The problem with my wrapper is that it is highly untested, in fact I only used the function bindtarget and only for 10 seconds or so.

使用下面的包装器,您可以创建一些小部件并宣布它支持接收拖动的文件.下面是一个例子:

With the wrapper below, you can create some widget and announce that it supports receiving dragged files. Here is one example:

# 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 程序,它比它提供的自己的 C 扩展更高.我没有包装这个更高级别的代码,但在 Python 中复制它可能比使用这个更低级别的包装更有趣.

Together with Tkdnd, you will find a tkdnd.tcl program which is a higher level over the own C extension it provides. I didn't wrap this higher level code, but it could be more interesting to replicate it in Python than to use this lower level wrapper.

这篇关于将资源管理器文件拖放到 tkinter 条目小部件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆