Instantiation vs. Hide/Show

This is prob’ly a more general Python question, but since I’m using wx.Python :slight_smile:

My application is an implementation of a piece of test equipment (connected by a serial/Bluetooth port to a h/w subsystem). I have a frame which is the main “instrument” and then a 2nd frame which is basically a keypad (with arrows) and is needed only at certain times.

I’m curious about instantiating the keypad only when I need it vs. instantiating it at initialization and hiding it until I need to show it. I’m not worried about speed so taking a few mSecs, or even 1 or 2 secs., to show the keypad is not an issue.

I expect the question is relative to speed (instantiation as needed) vs. memory (hide/show), neither of which is a critical issue in this app. I’m also interested in the implications of moving the keypad essentially to a method/procedure and how that impacts the scope (since the keypad wold now be “moved up a level”)…tho, maybe I’m visualizing that wrong.

Thx in advance and cheers…

Either is okay, so whichever makes the most sense to you for your application is probably the way you want to go. The only thing I would caution is that the exit of the MainLoop happens when the last top-level window (including hidden ones) is closed, so you need to ensure that the hidden window is closed when the main frame is closed. But it you make the keypad frame be a child of the main frame then that will happen automatically.

We take the “instantiate on demand” approach on a lot of our little dialogs, especially for those that are used only intermittently or not at all. Bind a menu event/hotkey to the event handler and off you go. But, to reinforce what Robin said, both are fine and if this particular dialog were used all the time, we might go the other way and build it up front and hide it.

class MainWindow(wx.Frame):
    def __init__(self, ...):
        self.finder = None
    ...
    def OnFinder(self, event):
        if self.finder is None:
            from gui.finder import Finder
            self.finder = Finder(parent=self)
        self.finder.Show(show=not self.finder.IsShown())  # Toggles display.

Robin (as usual, you have been helpful, yet again) and Eric (so helpful this time :slight_smile: Thx!

Based on your comments, instantiation-as-needed seems like the best approach in my app. This is a multifunction instrument and the keypad is needed when configuration/operating parameters are changed (and only 4/10 of those would need the keypad), so not that often, and when one (of nine) of the main functions is active (and it needs to be there all the time during that function).

I didn’t see any comments regarding my question about scope (still getting comfortable with that). Is that not really an issue? If I instantiate as needed, then the keypad comes as a result of a procedure call and will be in a different frame. Do I need to be mindful of how the keypad addresses widgets on the main frame (which is where any keypad events will do there processing), or this that inherently resolved by the nature of Python?

Thx again and cheers…

you don’t have to init self.finder, just ask:
if ‘finder’ not in vars(self):

You need to give yourself what I call an “access path.” In other words, give yourself a way to access the things you need to call methods on or access properties. In this case, if the keypad frame needs to do something with the main frame or tell it to do something, then maybe you will give the keypad a reference to the main window. Or vice/versa, or both. This is an example of tightly coupling discrete objects together, where one or both of them know details about the other. This is okay for smaller applications.

A better approach is to use some form of loose coupling, like a publish/subscribe pattern implementation like PyPubSub where components send messages, and others may subscribe to those messages if they are interested in them. That way the different components don’t need to know the nitty-gritty details of the others, or how to access them, or one component can change implementation if needed without affecting the others, etc.

Thx Robin. Most helpful, as usual.

And, as I usually do, I look for input from those most knowledgeable, and then I have to go experiment to see what it really means :slight_smile:

I’m about ready to start coding the keypad part of things so, in a short while, I should know how well I understand it…or not…

Cheers…

what about the ‘source’ parameter of the ‘Bind’ method of event handling: I haven’t experimented with it but from the docu it sounds like a strong coupling of two windows (which I think we are talking about here) ?
It’s not what I expected (sometimes I’m too optimistic even at my age)
Now I remember what my idea was all about (tight coupling): all the event handlers should be in the main frame and the events of the keypad should be bound to these handlers ( I mixed the target with the source and beg your pardon)

All widgets have an ID, and the ID is used within the event processing system to identify the source of the event you want to bind your handler to. It won’t help with connecting to events from other windows, just those that are within the current “containment hierarchy”. For example, say you have two buttons in your window that you want to catch events from at the frame level. You can use the source parameter of Bind to bind each to separate handler functions.

This wiki document may help: self.Bind vs. self.button.Bind

Well, I wondered about the ‘scope’ profconn1 was asking and thought he meant how to get some ‘message’ from the keypad to the main frame. So I looked at the ‘Bind’ and fell too quickly for this ‘source’ parameter as an option for crossing frames! But then I remembered (and it is very well pointed out in the documentation) that the handler of an event binding can be any callable and thus the ‘scope’ is unlimited as long as (as you pointed out) one has the address.
Thanks for the hint to the wiki and I hope my confusion isn’t as contagious as c…

Yes, something like this:

otherFrame.someWidget.Bind(wx.EVT_SOMETHING, self.myMethod)

does work, but IMO it’s a bit yucky because self needs to know the implementation details of otherFrame, and be changed if otherFrame’s implementation ever changes. It’s not bad for small applications, but it’s not sustainable when things start growing and evolving.