Hi, Adriaan
Wxpython triggers many events and provides an opportunity to catch them. All you have to do is define the state, handle the given events, drive your machine according to the context, and use the algorithm appropriately to do the output.
As you are doing and mentioned in the above posts, I think Wx.EVT_LEFT_DOWN and EVT_LEFT_UP should be the way to go, but perhaps there is no convenient wheel, or if any, buried in hundreds of thousands of code.
I like the FSM approach (see Finite-state machine - Wikipedia), and think this sample could be a help for you. Many authors have provided FSM libraries, and this is just an example of implementation.
import wx
class FSM(dict):
def __call__(self, event, *args):
context = self[self.state]
if event in context:
transaction = context[event]
self.state = transaction[0] # the state transits here
for act in transaction[1:]: # then execute the actions
act(*args)
IDLE, BUSY = 'idle', 'busy' # states
DN, MV, UP = 'press', 'dragging', 'release' # inputs
class Panel(wx.Panel):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.handler = FSM({
IDLE : {
DN : (BUSY, self.on_pressed),
UP : (IDLE, self.on_released)
},
BUSY : {
MV : (BUSY, self.on_motion),
UP : (IDLE, self.on_released),
},
})
self.handler.state = IDLE
## btn = wx.Button(self, label="Take me")
btns = [wx.Button(self, label=l)
for l in "The quick brown fox jumped over the lazy dog".split()]
for btn in btns:
btn.Bind(wx.EVT_LEFT_DOWN, lambda v: self.handler(DN, v))
btn.Bind(wx.EVT_LEFT_UP, lambda v: self.handler(UP, v))
btn.Bind(wx.EVT_MOTION, lambda v: self.handler(MV, v))
self.Bind(wx.EVT_BUTTON, print)
def on_pressed(self, evt):
print("I'm {}".format(self.handler.state))
self._org = evt.Position
evt.Skip() # skip to CaptureMouse
def on_released(self, evt):
print("I'm {}".format(self.handler.state))
evt.Skip() # skip to ReleaseMouse
def on_motion(self, evt):
btn = evt.EventObject
print("I'm {} at {}".format(self.handler.state, btn.Position))
btn.Position += evt.Position - self._org
evt.Skip()
if __name__ == "__main__":
app = wx.App()
frm = wx.Frame(None)
panel = Panel(frm)
frm.Show()
app.MainLoop()
From a night owl… 
This post is related to my old article A new idea how to enable Emacs-like multi-stroke keymap in wxPython and hint to boost menubar and accelerators