在Python GUI(GTK)中拖放文件

vdzxcuhz  于 2023-01-19  发布在  Python
关注(0)|答案(3)|浏览(222)

我想写一个小应用程序谁需要选定的文件数量,并存储的路径,一切为未来的事情。
基本上:
从Nautilus中选择混合(图像、音频、视频)文件(在本例中),将其拖放到此GUI中,并获得要写入列表的每个元素的绝对路径。
程序本身是不是一个问题,但我在最简单的任务失败,也许:创建一个GUI(我选择了GTK,但一切都会好的,只需要完成工作),接受元素并存储它们。
我在和Glade玩,但我甚至不确定这是不是正确的选择。
有人能帮助我构建这个GUI或指出一些资源吗?

wribegjk

wribegjk1#

这里有一个开始使用Glade、Gtk和Python的好方法:
http://python-gtk-3-tutorial.readthedocs.io/en/latest/builder.html
和拖放:
http://python-gtk-3-tutorial.readthedocs.io/en/latest/drag_and_drop.html
使用小型工作程序进行编辑:

#!/usr/bin/env python

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk
import os, sys


class GUI:
    def __init__(self):
        window = Gtk.Window()
        window.connect('destroy', Gtk.main_quit)
        textview = Gtk.TextView()
        enforce_target = Gtk.TargetEntry.new('text/plain', Gtk.TargetFlags(4), 129)
        textview.drag_dest_set(Gtk.DestDefaults.ALL, [enforce_target], Gdk.DragAction.COPY)
        textview.connect("drag-data-received", self.on_drag_data_received)
        #textview.drag_dest_set_target_list([enforce_target])
        window.add(textview)
        window.show_all()

    def on_drag_data_received(self, widget, drag_context, x,y, data,info, time):
        print (data.get_text())

def main():
    app = GUI()
    Gtk.main()
        
if __name__ == "__main__":
    sys.exit(main())
nr9pn0ug

nr9pn0ug2#

我已经尝试了@theGtknerd提供的示例,但没有效果。经过几个小时的调试,我用几行代码就可以使用这个示例了。

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk
import sys

class GUI:
    def __init__(self):
        window = Gtk.Window()
        window.connect('destroy', Gtk.main_quit)

        textview = Gtk.TextView()
        #                      (drag behaviour, targets (leave empty), action)
        textview.drag_dest_set(Gtk.DestDefaults.DROP, [], Gdk.DragAction.COPY)
        # add the ability to receive URIs (e.g. file paths)
        textview.drag_dest_add_uri_targets()
        textview.connect("drag-data-received", self.on_drag_data_received)

        window.add(textview)
        window.show_all()

    def on_drag_data_received(self, widget, drag_context, x,y, data,info, time):
        print(data.get_uris())
        #              (context, success, delete_from_source, time)
        Gtk.drag_finish(drag_context, True, False, time)
        # always call Gtk.drag_finish to receive as suggested by documentation

def main():
    GUI()
    Gtk.main()

if __name__ == "__main__":
    sys.exit(main())

本人意见:

  • 任何Gtk.Widget都可以通过.drag_dest_set()接收数据,但是需要在这里设置目标,或者调用添加目标的方法,比如.drag_dest_add_uri_targets()
  • Gtk.TextView似乎有一个bug,在第一次调用后drag-data-received信号重复了两次,因此处理程序被调用了两次。在这对调用中,第一次包含新数据,第二次包含以前的数据。
k97glaaz

k97glaaz3#

要避免两次调用drag-data-received...
你可以从鹦鹉螺,LibreOffice,gedit,一个来自Chrome的链接

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk
import sys, urllib

class GUI:
    def __init__(self):
        window = Gtk.Window()
        window.connect('destroy', Gtk.main_quit)

        textview = Gtk.TextView()

        # 'enforce_target1'
        enforce_target1 = Gtk.TargetEntry.new('text/uri-list', 0, 50)  # laisse passer les noms de fichiers avec pb d'accents (info = 50)      
        # add the ability to receive URIs (e.g. file paths)
        textview.drag_dest_set_target_list([enforce_target1])

        # add the ability to receive 'texts', 'link'
        textview.drag_dest_add_text_targets()       # gère correctement les textes, les liens (info = 0)

        # connect the signal "drag-data-received"  of the textview to the callback 'self.on_drag_data_received'
        textview.connect("drag-data-received", self.on_drag_data_received)

        window.add(textview)
        window.show_all()

    def on_drag_data_received(self, widget, drag_context, x,y, data,info, time):
        print(info)

        if info == 50:        # 'text/uri-list' from Nautilus
            data = data.get_data()
            # Si on a glissé un fichier depuis Nautilus :            
            # L'objet byte se termine par \r\n, il faut supprimer ces deux caractères
            # \r correspond à CR (Carriage Return) \n correspond à LF (Line Feed).
            if data[-2:] == b'\r\n':
                    print("     ...se termine par \\r CR (Carriage Return) et \\n correspond à LF (Line Feed)")
                    data  = data[:-2]
                    print(f"Data reçu : {data}")
            # Replacing '%20' with Space and  '%C3%A9' with é .... etc....
            data=urllib.parse.unquote(data.decode())         
            print(f"Data reçu  (unquote) : {data}")
            # Insert data in the the textview
            widget.get_buffer().insert_at_cursor(data)

        if info == 0 :
            print(data.get_text())
            print("The drop is done automatically on the textview")
            
        # Gtk.drag_finish(drag_context, True, False, time)
        # always call Gtk.drag_finish to receive as suggested by documentation

def main():
    GUI()
    Gtk.main()

if __name__ == "__main__":
    sys.exit(main())

相关问题