【问题标题】:wxPython: Handling drag-and-drop in a parent object - problem with event propagationwxPython:处理父对象中的拖放 - 事件传播问题
【发布时间】:2009-12-09 22:32:24
【问题描述】:

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

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

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

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

有人知道任何替代解决方案吗?是否有任何命令事件可用于启动拖动?或者还有什么我没有想到的?

【问题讨论】:

    标签: python drag-and-drop wxpython


    【解决方案1】:

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

    我已经在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()
    

    【讨论】:

      【解决方案2】:

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

      Panel 可以递归实现,也可以在 Panel 中有一个函数 addControl,只有这样的控件才会被 hook。

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

      如果您希望拖动控件用作整个组的拖动,那么您必须覆盖此类事件,但是通过仅拖动特殊的组合键或模式,您可以让子控件也有自己的行为。

      【讨论】:

        猜你喜欢
        • 2011-10-22
        • 2018-04-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-29
        • 1970-01-01
        • 1970-01-01
        • 2012-08-25
        相关资源
        最近更新 更多