How to repeat code in an OnButton event while mouse button is held down by user

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… :grinning:

:memo: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