Propagating event

Hi all,

I have an application where I had to build some custom widgets that should communicate between themselves through particular actions.

For instance, I have a widget that consists in loading a given file. When that file is loaded this should update the contents and appearance of the other widgets.

I recently read in the wx wiki that it was good to write widgets the most autonomous as possible. So taking into account that advisement, I think that one way

to make themselves communicate would be through custom events. The problem is that I managed to produce the custom event and to make the source widget

producing it but I do not manage to make the target widget receive the event.

You will find enclosed a
snippet that illustrates the problem. It is adapted from the wx python demo codes. Would you have any idea why the target widget

(MyWidget) does not receive the event ?

thanks a lot

Eric

PythonEvents.py (1.51 KB)

Would you have any idea why the target widget (MyWidget) does not receive the event ?

You send the instance of MyEvent to instance of MyButton's event
handler, which forwards evt, because it's a CommandEvent subclass
type, to the instance of TestPanel.

However TestPanel does not bind to EVT_BUTTON_CLICKPOS event types so
it ignores that event and so TestPanel does not send instance of
MyEvent to any local or child EvtHandlers. Meaning MyWidget doesn't
get it.

In TestPanel, where you create the button and MyWidget, bind to
EVT_BUTTON_CLICKPOS. You could use the MyWidget EVT_BUTTON_CLICKPOS
handler.

I've attached two files. One with minor changes to your code and one
that shows several other ways to do the same thing.

The PythonEvents_editted.py has some other notes you might consider
important; like binding to LEFT_CLICK and EVT_BUTTON at the same time;
or reminder of righty and lefty user issues.

btw, I can see some nice button customizations based on where you
click on a button.

PythonEvents_minor_fix.py (2.36 KB)

PythonEvents_editted.py (9.76 KB)

thanks a lot for all this information. I understand much better the event mechanism now.

Eric

···

De : Dev Player devplayer@gmail.com
À : wxpython-users@googlegroups.com
Envoyé le : Samedi 26 Novembre 2011 5h46
Objet : Re: [wxPython-users] Propagating event

Would you have any idea why the
target widget (MyWidget) does not receive the event ?
You send the instance of MyEvent to instance of MyButton’s event
handler, which forwards evt, because it’s a CommandEvent subclass
type, to the instance of TestPanel.

However TestPanel does not bind to EVT_BUTTON_CLICKPOS event types so
it ignores that event and so TestPanel does not send instance of
MyEvent to any local or child EvtHandlers. Meaning MyWidget doesn’t
get it.

In TestPanel, where you create the button and MyWidget, bind to
EVT_BUTTON_CLICKPOS. You could use the MyWidget EVT_BUTTON_CLICKPOS
handler.

I’ve attached two files. One with minor changes to your code and one
that shows several other ways to do the same thing.

The PythonEvents_editted.py has some other notes you might consider
important; like binding to LEFT_CLICK and EVT_BUTTON at the same time;
or reminder of righty and lefty user issues.

btw, I can see some
nice button customizations based on where you
click on a button.


To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en

there is just one point that is still not clear to me.

In my application I have a generic dialog used to setup and start some analysis selected by the user.

By construction this dialog acts as a container/factory whose widgets contents may differ from one kind of analysis to another. In doing so,

I separate the mechanism to launch an analysis and the analysis by itself that should not care about the process behind the scene to launch it.

When building such a container dialog, I should just give its widgets contents and not their bindings otherwise my dialog will not be generic anymore.

That is why I need autonomous enough widgets to communicate directly between themselves shortcutting the host dialog.

From
the nice set of examples you gave me, dev-player, whatever the method, it always end up with a binding defined in the testpanel class. This is

what I would like to avoid. Say that I have a custom widget class c1 that post an event type e1 and a custom widget class that I want to be sensitive

to e1. Why should I pass by their container to make themselves communicate ?

Does my construction make sense to you (container dialog + widget that defines their binding to communicate directly between themselves) ?

thanks a lot

Eric

···

De : Pellegrini Eric ericpellegrini@yahoo.fr
À :wxpython-users@googlegroups.comwxpython-users@googlegroups.com
Envoyé le : Samedi 26 Novembre 2011 9h05
Objet : Re : [wxPython-users] Propagating event - solved

thanks a lot for all this information. I understand much better the event mechanism now.

Eric


De : Dev Player devplayer@gmail.com
À : wxpython-users@googlegroups.com
Envoyé le : Samedi 26 Novembre 2011 5h46
Objet : Re: [wxPython-users] Propagating event

Would you have any idea why the
target widget (MyWidget) does not receive the event ?
You send the instance of MyEvent to instance of MyButton’s event
handler, which forwards evt, because it’s a CommandEvent subclass
type, to the instance of TestPanel.

However TestPanel does not bind to EVT_BUTTON_CLICKPOS event types so
it ignores that event and so TestPanel does not send instance of
MyEvent to any local or child EvtHandlers. Meaning MyWidget doesn’t
get it.

In TestPanel, where you create the button and MyWidget, bind to
EVT_BUTTON_CLICKPOS. You could use the MyWidget EVT_BUTTON_CLICKPOS
handler.

I’ve attached two files. One with minor changes to your code and one
that shows several other ways to do the same thing.

The PythonEvents_editted.py has some other notes you might consider
important; like binding to LEFT_CLICK and EVT_BUTTON at the same time;
or reminder of righty and lefty user issues.

btw, I can see some
nice button customizations based on where you
click on a button.


To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en

To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com

or visit http://groups.google.com/group/wxPython-users?hl=en

Take a look at the wx.lib.pubsub module. This is an implementation of the Publish/Subscribe or Observer design pattern, and it lets you have parts of your program send messages and other parts of your program can subscribe to see those messages, but the various parts do not need to know about each other.

Ah, I see from your next message that you are investigating pubsub already. Good job! :slight_smile:

···

On 11/26/11 12:52 AM, Pellegrini Eric wrote:

From the nice set of examples you gave me, dev-player, whatever the
method, it always end up with a binding defined in the testpanel class.
This is
what I would like to avoid. Say that I have a custom widget class c1
that post an event type e1 and a custom widget class that I want to be
sensitive
to e1. Why should I pass by their container to make themselves communicate ?

--
Robin Dunn
Software Craftsman

there is just one point that is still not clear to me.

In my application I have a generic dialog used to setup and start some
analysis selected by the user.
By construction this dialog acts as a container/factory whose widgets
contents may differ from one kind of analysis to another. In doing so,
I separate the mechanism to launch an analysis and the analysis by itself
that should not care about the process behind the scene

"scene" I read as GUI, graphical user interface.
This sounds like it will fit the observer pattern very nicely. Google
"python observer pattern".

to launch it.
When building such a container dialog, I should just give its widgets
contents and not their bindings otherwise my dialog will not be generic
anymore.

"Binding" sounds very "connected" but it is not. A binding means "send
me a message and I'll pass it to a method that might or might not
process the event. But a binding is not necessarily one method in one
object (a dialog) calling directly another method in a "special"
widget.

That is why I need autonomous enough widgets to communicate directly between
themselves shortcutting the host dialog.

When you say "host dialog" do you mean "parent frame"? As in, the
frame + panel is "hosting" the dialog and the "special" widget.

From the nice set of examples you gave me, dev-player, whatever the method,
it always end up with a binding defined in the testpanel class. This is
what I would like to avoid. Say that I have a custom widget class c1 that
post an event type e1 and a custom widget class that I want to be sensitive
to e1. Why should I pass by their container to make themselves communicate ?

Does my construction make sense to you (container dialog + widget that
defines their binding to communicate directly between themselves) ?

Yes I understand what you want. The PubSub will post a message to a
queue. and any listener who wants it can pull that message from the
PubSub queue. This is a loose coupling between widgets. This will come
very close to what you seek.

But let me ask you some questions.
1. What types of signals does your dialog send out to
whom-ever-may-be-listening.
Your dialog must know what -kind- of message to send. Whatever kind of
thing that is, it's an instance of some Python class.

2. Where does your dialog -put- that message/event "thing"? Into some
queue or list. Your dialog needs a name to reference that queue.

3. What signals does your "special" widget look for? It must know what
-kind- of message to look for. Whatever kind of thing that is, it's an
instance of some class.

4. Where does your widget read this signal from? Your widget must have
a queue or list to look in to see if there are any
messages/events/objects in it. Often such an object, a queue or event
list, is referenenced by a variable name.

Whether it uses a the OS eventing system or Python's pubsub, or even
an object's attributes as flags, each of those things are spots in
computer memory and both the dialog and widget need access to that
memory or copies of it.

Most of the examples I showed link the special widget to the dialog
through the parent window frame. Why? Because the parent is the one
item that should KNOW about the dialog box AND the special widget.
AND, both the dialog box and the special widget need a "place" to
store it's data OR an API (also called an interface) to to allow other
objects to get that data.

SO the question is: How do YOU want to pass data?
    1. through a messaging system (ie events or pubsub)
    2. through each objects API.
    3. there are other ways, PIPEs, threads and other not so great ideas.

If you choose the messaging system, then both your dialog box and
special widget need to know how to read and write that event/message
AND both objects need to ask someone for the storage queue. I used the
frame window via Bind() to supply the "named" event/message queue to
both widgets, the dialog box and special widget.

Your initial example showed usage of events so I stuck with connecting
your widgets via events.

By the way, you didn't have to create a custom event type. You could
have (ab)used one already defined in the OS, like EVT_IDLE. But that
confuses people reading your code and just asks for trouble. I thought
the custom event was better for clarity. To me there is little
difference between custom events and Pubsub; except perhaps pubsub is
more transferable to "other" gui libraries, other, then say, wxPython.

Also;

your structure is:

             OS + wx.App
              >
              V
            wx.Frame

···

On Sat, Nov 26, 2011 at 3:52 AM, Pellegrini Eric <ericpellegrini@yahoo.fr> wrote:
              >
        ------+-----------
        > >
    wx.DialogBox wx.special_widget
        ^ ^
        > >
       OS OS

Do you see the path of how the dialog box needs to communicate with
special widget, or in your case the special widget to get
communcication from the dialogbox? Either via the OS directly or
through the frame. Via the frame using a frame attribute or method
like Bind().

At the moment my brain isn't thinking of other ways.