wxPython:处理父对象中的拖放 - 事件传播的问题

时间:2009-12-09 22:32:24

标签: python drag-and-drop wxpython

我有一个wxPython程序,我希望能够拖动控件组来重新排序它们。每组控件都在一个面板上,我希望面板对象能够处理拖放。

目前,如果您单击并拖动面板本身,它可以正常工作,但如果您单击面板内的任何控件,它将无效。这是因为我用来触发拖动的wx.EVT_LEFT_DOWN事件不是命令事件,因此不会传播到父面板。

我能想到的唯一方法是将该事件绑定到面板的处理程序,以便面板上的每个控件。

这对我来说似乎不是很优雅 - 要么我必须在创建每个子事件时明确地执行它,这会破坏封装,或者面板通过子控件进行递归并执行绑定 - 这似乎很危险,因为个人控件可能已经将该事件用于其他目的。理想情况下,我希望面板上的控件不需要了解有关DnD的任何信息。

有没有人知道任何替代解决方案?是否有任何可用于启动拖动的命令事件?还是其他我没有想过的事情?

2 个答案:

答案 0 :(得分:2)

我意识到这已经很晚了,但万一它仍然对某人有帮助:

我在my (related) question的代码中完成了这项工作:

import wx

app = wx.App(False)
d = {}

def wMouseDown(e):
    print "!!!", e.GetEventObject()

def MouseDown(e):   
    o           = e.GetEventObject()
    sx,sy       = panel.ScreenToClient(o.GetPositionTuple())
    dx,dy       = panel.ScreenToClient(wx.GetMousePosition())
    o._x,o._y   = (sx-dx, sy-dy)
    d['d'] = o

def MouseMove(e):
    try:
        if 'd' in d:
            o = d['d']
            x, y = wx.GetMousePosition()
            o.SetPosition(wx.Point(x+o._x,y+o._y))
    except: pass

def MouseUp(e):
    try:
        if 'd' in d: del d['d']
    except: pass

frame = wx.Frame(None, -1, 'simple.py')
panel = wx.Panel(frame)
box = wx.BoxSizer(wx.VERTICAL)
button1 = wx.Button(panel, -1, "foo")
box.Add(button1, 0, wx.ALL, 10)
button2 = wx.Button(panel, -1, "bar")
box.Add(button2, 0, wx.ALL, 10)

button1.Bind(wx.EVT_LEFT_DOWN, MouseDown)
button2.Bind(wx.EVT_LEFT_DOWN, MouseDown)

button1.Bind(wx.EVT_MOTION, MouseMove)
button2.Bind(wx.EVT_MOTION, MouseMove)

button1.Bind(wx.EVT_LEFT_UP, MouseUp)
button2.Bind(wx.EVT_LEFT_UP, MouseUp)

panel.Bind(wx.EVT_MOTION, MouseMove)
panel.Bind(wx.EVT_LEFT_UP, MouseUp)

panel.SetSizer(box)
panel.Layout()
frame.Show()

app.MainLoop()

答案 1 :(得分:1)

IMO最好的方法是,Panel应绑定到控件wx.EVT_LEFT_DOWN并仅在特殊键组合时拖动,例如按下cntrl-alt-d

Panel可以递归执行,或者在Panel中有一个函数,addControl只会挂钩这样的控件。

您的观点“单个控件可能已经将该事件用于其他目的”无效,因为您可以使用该事件进行拖动,不能同时使用。

如果你想将控制拖动用作整个组的拖动,那么你必须覆盖这样的事件,但是只需要拖动特殊的组合键或模式,你就可以让儿童控制也有他们的行为。