wxPython中的拖放

在计算机图形用户界面中,拖放是指导击一个虚构对象并将其拖到不同的地位或另一个虚构对象上的动作(或反对该动作)。一般来说,它能够用来调用多种操作,或者在两个形象对象之间创立各种类型的关联。

拖放操作能够让你直观地实现简单的事件。

在拖放操作中,咱们将一些数据从数据源拖到数据指标上。所以咱们必须要有

  • 一些数据
  • 一个数据源
  • 一个数据指标

在wxPython中,咱们有两个预约义的数据指标。wx.TextDropTargetwx.FileDropTarget

wx.TextDropTarget

wx.TextDropTarget是一个预约义的用于解决文本数据的投放指标。

#dragdrop_text.pyfrom pathlib import Pathimport osimport wxclass MyTextDropTarget(wx.TextDropTarget):    def __init__(self, object):        wx.TextDropTarget.__init__(self)        self.object = object    def OnDropText(self, x, y, data):        self.object.InsertItem(0, data)        return Trueclass Example(wx.Frame):    def __init__(self, *args, **kw):        super(Example, self).__init__(*args, **kw)        self.InitUI()    def InitUI(self):        splitter1 = wx.SplitterWindow(self, style=wx.SP_3D)        splitter2 = wx.SplitterWindow(splitter1, style=wx.SP_3D)        home_dir = str(Path.home())        self.dirWid = wx.GenericDirCtrl(splitter1, dir=home_dir,                 style=wx.DIRCTRL_DIR_ONLY)                        self.lc1 = wx.ListCtrl(splitter2, style=wx.LC_LIST)        self.lc2 = wx.ListCtrl(splitter2, style=wx.LC_LIST)        dt = MyTextDropTarget(self.lc2)        self.lc2.SetDropTarget(dt)                self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.OnDragInit, id=self.lc1.GetId())        tree = self.dirWid.GetTreeCtrl()        splitter2.SplitHorizontally(self.lc1, self.lc2, 150)        splitter1.SplitVertically(self.dirWid, splitter2, 200)        self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelect, id=tree.GetId())        self.OnSelect(0)        self.SetTitle('Drag and drop text')        self.Centre()    def OnSelect(self, event):        list = os.listdir(self.dirWid.GetPath())        self.lc1.ClearAll()        self.lc2.ClearAll()        for i in range(len(list)):            if list[i][0] != '.':                self.lc1.InsertItem(0, list[i])    def OnDragInit(self, event):        text = self.lc1.GetItemText(event.GetIndex())        tdo = wx.TextDataObject(text)        tds = wx.DropSource(self.lc1)        tds.SetData(tdo)        tds.DoDragDrop(True)def main():    app = wx.App()    ex = Example(None)    ex.Show()    app.MainLoop()if __name__ == '__main__':    main()

<img src="https://mymarkdowm.oss-cn-beijing.aliyuncs.com/markdownimg/image-20201031161853768.png" alt="image-20201031161853768" style="zoom:50%;" />

在本例中,咱们在wx.GenericDirCtrl中显示了一个文件系统。所选目录的内容显示在右上角的列表控件中,文件名能够拖放到右下角的列表控件中。

def OnDropText(self, x, y, data):    self.object.InsertItem(0, data)    return True    

当咱们将文本数据投放到指标上时,通过InsertItem()办法将数据插入到列表控件中。

dt = MyTextDropTarget(self.lc2)self.lc2.SetDropTarget(dt)  

一个下拉指标被创立。咱们应用SetDropTarget()办法将投放指标设置为第二个列表控件。

self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.OnDragInit, id=self.lc1.GetId()) 

当拖动操作开始时,会调用OnDragInit()办法。

def OnDragInit(self, event):    text = self.lc1.GetItemText(event.GetIndex())    tdo = wx.TextDataObject(text)    tds = wx.DropSource(self.lc1)    ...

OnDragInit()办法中,咱们创立一个wx.TextDataObject,其中蕴含咱们的文本数据。从第一个列表控件中创立一个投放源。

tds.SetData(tdo)tds.DoDragDrop(True)

咱们用SetData()为投放源设置数据,用DoDragDrop()启动拖放操作。

wx.FileDropTarget

wx.FileDropTarget是一个能够承受从文件管理器中拖动的文件的投放指标。

#dragdrop_file.pyimport wxclass FileDrop(wx.FileDropTarget):    def __init__(self, window):        wx.FileDropTarget.__init__(self)        self.window = window    def OnDropFiles(self, x, y, filenames):        for name in filenames:            try:                file = open(name, 'r')                text = file.read()                self.window.WriteText(text)            except IOError as error:                msg = "Error opening file\n {}".format(str(error))                dlg = wx.MessageDialog(None, msg)                dlg.ShowModal()                return False            except UnicodeDecodeError as error:                msg = "Cannot open non ascii files\n {}".format(str(error))                dlg = wx.MessageDialog(None, msg)                dlg.ShowModal()                return False            finally:                file.close()        return Trueclass Example(wx.Frame):    def __init__(self, *args, **kw):        super(Example, self).__init__(*args, **kw)        self.InitUI()    def InitUI(self):        self.text = wx.TextCtrl(self, style = wx.TE_MULTILINE)        dt = FileDrop(self.text)        self.text.SetDropTarget(dt)        self.SetTitle('File drag and drop')        self.Centre()def main():    app = wx.App()    ex = Example(None)    ex.Show()    app.MainLoop()if __name__ == '__main__':    main()

<img src="https://mymarkdowm.oss-cn-beijing.aliyuncs.com/markdownimg/image-20201031162055685.png" alt="image-20201031162055685" style="zoom:50%;" />

这个例子创立了一个简略的wx.TextCtrl。咱们能够从文件管理器中拖动文本文件到控件中。

def OnDropFiles(self, x, y, filenames):    for name in filenames:    ...

咱们能够一次拖放多个文件。

try:    file = open(name, 'r')    text = file.read()    self.window.WriteText(text)

咱们以只读模式关上文件,获取其内容并将内容写入文本管制窗口。

except IOError as error:    msg = "Error opening file\n {}".format(str(error))    dlg = wx.MessageDialog(None, msg)    dlg.ShowModal()    return False

如果呈现输出/输入谬误,咱们将显示一个音讯对话框并终止操作。

self.text = wx.TextCtrl(self, style = wx.TE_MULTILINE)dt = FileDrop(self.text)self.text.SetDropTarget(dt)

wx.TextCtrl是拖放指标。