Sign in to follow this  
Oysterman

[wxPython] Making a Panel draggable

Recommended Posts

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?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this