wxpythonpypubsub

How to listen to a frame size/move change event in wxpython


What is the correct way to publish.listen to a size change event in wxpython?

I'm sure this is simple, but I can't get my head around how to implement this between classes well (please forgive any newbie obvious errors).

I can send the event using pypubsub, but this only caught by the listener when the UI class is created (i.e. listened once, not when the frame is subsequently resized).

listeners:

    # listeners - define before the event
    pub.subscribe(self.on_resized, 'size_changed')
    pub.subscribe(self.on_relocated, 'pos_changed')

publishers:

def on_size(self, event):
    _size = event.GetSize()
    pub.sendMessage('size_changed', size=_size)
    
def on_move(self, event):
    _pos = event.GetPosition()
    pub.sendMessage('pos_changed', pos=_pos)
    

I've tried using a CallAfter - but this doesn't seem to help (not too sure what I'm doing with this, but thought it may call the event after)

def on_size(self, event):
    _size = event.GetSize()
    wx.CallAfter(pub.sendMessage, 'size_changed', size=_size)


def on_move(self, event):
    _pos = event.GetPosition()
    wx.CallAfter(pub.sendMessage, 'pos_changed', pos=_pos)

I also tried a second varient of CallAfter, which seems to be listened to twice (an improvement?), but I understand this to be incorrectly formatted by the resultant AssertionError

def on_size(self, event):
    _size = event.GetSize()
    # test incorrect formatting of call after...
    wx.CallAfter(pub.sendMessage('size_changed', size=_size))

def on_move(self, event):
    _pos = event.GetPosition()
    pub.sendMessage('pos_changed', pos=_pos)

Thanks in advance for any help/pointers

minimal demo:

import pubsub.pub as pub
import wx


class UI(wx.Frame):
    def __init__(self, *args, **kwargs):

        # init base class
        super().__init__(*args, **kwargs)

        # bindings
        self.Bind(wx.EVT_MOVE, self.on_move)
        self.Bind(wx.EVT_SIZE, self.on_size)

    def on_size(self, event):
        _size = event.GetSize()
        print('[UI] resized to :', _size)
        # broadcast new size
        pub.sendMessage('size_changed', size=_size)
        # wx.CallAfter(pub.sendMessage, 'size_changed', size=_size)

        # test incorrect formatting of call after...
        # wx.CallAfter(pub.sendMessage('size_changed', size=_size))

    def on_move(self, event):
        _pos = event.GetPosition()
        print('[UI] moved to :', _pos)
        # broadcast new location
        pub.sendMessage('pos_changed', pos=_pos)
        # wx.CallAfter(pub.sendMessage, 'pos_changed', pos=_pos)



class CustomFrame(object):

    def __init__(self, parent=None, _id=wx.ID_ANY, title='test'):

        # listeners - define before the event
        pub.subscribe(self.on_resized, 'size_changed')
        pub.subscribe(self.on_relocated, 'pos_changed')

        self._id = _id
        self._ui = UI(parent=parent, id=_id, title=title)
        self._ui.Show()

    def on_resized(self, size):
        print('[CustomFrame] The new size is :=', size)
        # do something with the new size

    def on_relocated(self, pos):
        print('[CustomFrame] The new location is :=', pos)
        # do something with the new position


if __name__ == '__main__':
    app = wx.App()
    CustomFrame(title='Demo')
    app.MainLoop()

Solution

  • I think it's because CustomFrame isn't a frame, it's some object.
    If you change the definition of CustomFrame to the following code, it should work. That said, it's unclear what you're trying to achieve here.

    class CustomFrame(wx.Frame):
    
        def __init__(self, parent=None, _id=wx.ID_ANY, title='test'):
    
            # init base class
            super(CustomFrame, self).__init__(parent)
            # listeners - define before the event
            pub.subscribe(self.on_resized, 'size_changed')
            pub.subscribe(self.on_relocated, 'pos_changed')
    
            self._id = _id
            self._ui = UI(parent=self, id=_id, title=title)
            self._ui.Show()