wxPython 中的拖放
最后修改于 2023 年 1 月 10 日
在计算机图形用户界面中,拖放是指点击一个虚拟对象并将其拖到另一个位置或另一个虚拟对象上的动作(或对该动作的支持)。一般来说,它可用于调用许多类型的动作,或在两个抽象对象之间创建各种类型的关联。
拖放操作使您能够直观地完成复杂的事情。
在拖放操作中,我们从数据源拖动一些数据到数据目标。因此我们必须有
- 一些数据
- 一个数据源
- 一个数据目标
在 wxPython 中,我们有两个预定义的数据目标:wx.TextDropTarget 和 wx.FileDropTarget。
wx.TextDropTarget
wx.TextDropTarget 是一个预定义的拖放目标,用于处理文本数据。
#!/usr/bin/env python
"""
ZetCode wxPython tutorial
In this example, we drag and drop text data.
author: Jan Bodnar
website: www.zetcode.com
last modified: July 2020
"""
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,它包含我们的文本数据。 从第一个列表控件创建拖动源。
tds.SetData(tdo) tds.DoDragDrop(True)
我们使用 SetData() 将数据设置到拖动源,并使用 DoDragDrop() 启动拖放操作。
wx.FileDropTarget
wx.FileDropTarget 是一个拖放目标,它接受从文件管理器拖动的文件。
#!/usr/bin/env python
"""
ZetCode wxPython tutorial
In this example, we drag and drop files.
author: Jan Bodnar
website: www.zetcode.com
last modified: July 2020
"""
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 中的拖放操作。