[wxPython] Making a Panel draggable

Started by
0 comments, last by ravengangrel 14 years, 10 months ago
Hi all, Long story short, I'm exploring wxPython, and I want to make it possible for a user to drag panels around in a Frame using the mouse. My spontaneous approach was to do something like this:
import wx

class Draggable(wx.Panel):
    def __init__(self, parent, size):
        wx.Panel.__init__(self, parent, size=size)
        self.SetBackgroundColour(wx.BLACK)
        self.Bind(wx.EVT_LEFT_DOWN, self.OnClick)
        self.Bind(wx.EVT_LEFT_UP, self.OnRelease)
        self.Bind(wx.EVT_MOTION, self.OnMouseMove)
    def OnClick(self, e):
        self.clickDelta = e.GetPositionTuple()
        self.oldPos = self.GetPositionTuple()
        self.SetBackgroundColour(wx.WHITE)
        self.Refresh()
    def OnRelease(self, e):
#        self.SetPosition(self.oldPos)
        self.SetBackgroundColour(wx.BLACK)
        self.Refresh()
    def OnMouseMove(self, e):
        if e.Dragging():
            dx, dy = self.clickDelta
            mx, my = e.GetPositionTuple()
            x,y = self.GetPositionTuple()
            x += mx-dx
            y += my-dy
            self.SetPosition((x,y))
            self.Refresh()

class Frame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1)
        sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(sizer)

        d = Draggable(self, (50, 50))
        d.SetPosition((50, 50))

class App(wx.App):
    def OnInit(self):
        f = Frame()
        self.SetTopWindow(f)
        f.Show()
        return True

app = App(0)
app.MainLoop()

However, this approach makes it possible for the user to drag the things around faster than the event handling seems to be able to cope with. If you drag fast enough, you can make the mouse leave the panel while dragging it, messing everything up. I figure I could create a specific Panel class that functions as a container for Draggables. I'd register a Draggable with this container, and process the EVT_MOTION events in the container rather than in the individual Draggables. I like the first approach a lot better though, and I've successfully implemented it before in a similar way in Java/Swing. Is there a way I can make the first approach work well in wxPython?
Advertisement
This is not python related, but I think this could help, specifically the Vadim post about wxEVT_MOUSE_CAPTURE_CHANGED. I guess in wxPython its wx.EVT_MOUSE_CAPTURE_CHANGED

This topic is closed to new replies.

Advertisement