在计算机图形用户界面中,拖放是单击虚拟对象并将其拖动到不同位置或其他虚拟对象的动作(或支持动作)。 一般来说,它可以用来执行多种动作,或者在两个抽象对象之间创建各种类型的关联。
拖放操作使您能够直观地完成复杂的事情。
在拖放操作中,我们将一些数据从数据源拖动到数据目标。 所以我们必须有:
- Some data
- A data source
- A data target
在wxPython中,我们有两个预定义的数据目标: wx.TextDropTarget
and wx.FileDropTarget
.
wx.TextDropTarget
是处理文本数据的预定义放置目标。
dragdrop_text.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
ZetCode wxPython tutorial
In this example, we drag and drop text data.
author: Jan Bodnar
website: www.zetcode.com
last modified: May 2018
"""
from pathlib import Path
import os
import wx
class 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 True
class 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()
在这个例子中,我们在 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
,它包含我们的文本数据。 从第一个列表控件创建放置源 drop source。
tds.SetData(tdo)
tds.DoDragDrop(True)
我们使用 SetData()
将数据设置到放置源,并使用 DoDragDrop()
启动拖放操作。
wx.FileDropTarget
是一个放置目标,它接受从文件管理器拖动的文件。
dragdrop_file.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
ZetCode wxPython tutorial
In this example, we drag and drop files.
author: Jan Bodnar
website: www.zetcode.com
last modified: May 2018
"""
import wx
class 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 True
class 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()
该示例创建一个简单的 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
是放置目标。
在本章中,我们使用 wxPython 进行了拖放操作。