2009-12-09 15 views
0

我有一个wxPython程序,我希望能够拖动各组控件来重新排序它们。每组控件都在一个面板上,我希望面板对象能够处理拖放操作。wxPython:在父对象中处理拖放 - 事件传播的问题

目前,如果您在面板上单击并拖动它,它将起作用,但如果您单击面板内的任何控件,则它不起作用。这是因为我用来触发拖动的wx.EVT_LEFT_DOWN事件不是一个命令事件,所以不会传播到父面板。

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

这对我来说看起来并不是很优雅 - 或者当我创建每个子事件时打开封装,或者面板通过子控件递归并进行绑定 - 这看起来很危险,因为个别控件可能已经将该事件用于其他目的。理想情况下,我希望面板上的控件不需要知道有关DnD的任何信息。

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

回答

1

IMO最好的办法是,Panel应该绑定到控件的wx.EVT_LEFT_DOWN并且只有在特殊的组合键例如cntrl-alt-d被按下

面板可以递归地做到这一点,或者在Panel,addControl中有一个函数,只有这样的控件会被挂钩。

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

如果你想拖动控件来作为整个组的拖动,那么你必须重写这样的事件,但只要拖动一些特殊的组合键或模式,你就可以让子控件也有它们的行为。

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()