gpt4 book ai didi

python - 在 wxPython 中进行拖放的 OLE 方式

转载 作者:可可西里 更新时间:2023-11-01 10:10:32 25 4
gpt4 key购买 nike

我有一个在 MS Windows 上运行的 wxPython 应用程序,我希望它支持在其实例之间拖放(因此用户打开我的应用程序 3 次并将数据从一个实例拖到另一个实例)。

wxPython 中的简单拖放就是这样工作的:

  1. 用户发起拖动:源窗口将必要的数据打包到wx.DataObject()中,创建新的wx.DropSource,设置其数据并调用dropSource.DoDragDrop()
  2. 用户将数据拖放到目标窗口:拖放目标调用库函数 GetData() 将实际数据传输到其 wx.DataObject 实例,最后 - dataObject.GetData() 解压实际数据。

我想要一些更复杂的拖放功能,允许用户选择拖放之后他拖放的数据。
我的梦想场景:

  1. 用户启动拖动:只有一些指向源窗口的指针被打包(一些函数或对象)。
  2. 用户将数据拖放到目标窗口:显示一个漂亮的对话框,询问用户他选择了哪种拖放模式(例如 - 仅拖放歌曲标题,或歌曲标题和艺术家姓名或拖放的整个专辑艺术家)。
  3. 用户选择拖放模式:放置目标调用拖动数据对象上的一些函数,然后从拖动源检索数据并将其传输到放置目标。

我梦想的场景在 MS Windows 中似乎是可行的,但是 wxWidgets 和 wxPython 的文档非常复杂和模糊。并非所有 wx.DataObject 类在 wxPython 中都可用(仅 wx.PySimpleDataObject),所以我希望有人分享他使用这种方法的经验。是否可以在 wxPython 中实现这种行为而不必直接在 winAPI 中对其进行编码?

编辑:Toni Ruža 通过有效的拖放示例给出了答案,但这并不是我梦想的场景。他的代码在数据被放下时操纵数据(HandleDrop() 显示弹出菜单),但数据在拖动开始时准备(在 On_ElementDrag() 中)。在我的应用程序中应该有三种不同的拖放模式,其中一些需要耗时的数据准备。这就是为什么我想将数据检索推迟到用户删除数据并选择(可能代价高昂的)d&d 模式的那一刻。

对于内存保护问题——我想使用 OLE 机制进行进程间通信,就像 MS Office 那样。您可以复制 Excel 图表并将其粘贴到 MS-Word 中,它的行为类似于图像(嗯,有点)。由于它有效,我相信它可以在 winAPI 中完成。我只是不知道我是否可以在 wxPython 中对其进行编码。

最佳答案

因为您不能使用 standard 之一数据格式来存储对 python 对象的引用我建议您使用文本数据格式来存储方法调用所需的参数,而不是创建新的数据格式。无论如何,将一个对象的引用从一个应用程序传递到另一个应用程序是没有好处的,因为所讨论的对象将不可访问(还记得内存保护吗?)。

这是您的要求的一个简单示例:

import wx


class TestDropTarget(wx.TextDropTarget):
def OnDropText(self, x, y, text):
wx.GetApp().TopWindow.HandleDrop(text)

def OnDragOver(self, x, y, d):
return wx.DragCopy


class Test(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None)

self.numbers = wx.ListCtrl(self, style = wx.LC_ICON | wx.LC_AUTOARRANGE)
self.field = wx.TextCtrl(self)

sizer = wx.FlexGridSizer(2, 2, 5, 5)
sizer.AddGrowableCol(1)
sizer.AddGrowableRow(0)
self.SetSizer(sizer)
sizer.Add(wx.StaticText(self, label="Drag from:"))
sizer.Add(self.numbers, flag=wx.EXPAND)
sizer.Add(wx.StaticText(self, label="Drag to:"), flag=wx.ALIGN_CENTER_VERTICAL)
sizer.Add(self.field)

for i in range(100):
self.numbers.InsertStringItem(self.numbers.GetItemCount(), str(i))

self.numbers.Bind(wx.EVT_LIST_BEGIN_DRAG, self.On_ElementDrag)
self.field.SetDropTarget(TestDropTarget())

menu_id1 = wx.NewId()
menu_id2 = wx.NewId()
self.menu = wx.Menu()
self.menu.AppendItem(wx.MenuItem(self.menu, menu_id1, "Simple copy"))
self.menu.AppendItem(wx.MenuItem(self.menu, menu_id2, "Mess with it"))
self.Bind(wx.EVT_MENU, self.On_SimpleCopy, id=menu_id1)
self.Bind(wx.EVT_MENU, self.On_MessWithIt, id=menu_id2)

def On_ElementDrag(self, event):
data = wx.TextDataObject(self.numbers.GetItemText(event.Index))
source = wx.DropSource(self.numbers)
source.SetData(data)
source.DoDragDrop()

def HandleDrop(self, text):
self._text = text
self.PopupMenu(self.menu)

def On_SimpleCopy(self, event):
self.field.Value = self._text

def On_MessWithIt(self, event):
self.field.Value = "<-%s->" % "".join([int(c)*c for c in self._text])


app = wx.PySimpleApp()
app.TopWindow = Test()
app.TopWindow.Show()
app.MainLoop()

On_SimpleCopy 和 On_MessWithIt 之类的方法在拖放后执行,因此您可能想要执行的任何冗长操作都可以根据您通过拖动传输的文本或其他标准类型的数据(在我的例子中为 self._text)执行,然后看...没有 OLE :)

关于python - 在 wxPython 中进行拖放的 OLE 方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/476142/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com