Working on my first wxpython program on Windows. I have a couple of TextCtrls and some buttons at the bottom. I wanted to have a panel containing TextCtrls within a frame so I could tab between TextCtrls but my buttons needed to be in the frame so they could close it. The EVT_TEXT_ENTER events of the TextCtls control whether the ok button is enabled. And in turn, the function called from the ok button refers to the values of the TextCtrls. As it stands now, I could not use a panel cause I could not figure out how to reference the buttons from the EVT_TEXT_ENTER event and vice versa. Does that make any sense? I know its an easy answer but like I said, I'm just gittin started.
In event-oriented programs, it seems a good idea to
handle as much communication between program elements
as possible with events. What I would like to do is
the following:
I have a wxTreeCtrl object, and each time an item is
selected, a message window should display details
about the item. The wxTreeCtrl contains all relevant
data about its member items. The straightforward way
to implement this would probably be to pass the
EVT_TREE_SEL_CHANGED event through to the main window,
which can extract the relevant information from the
wxTreeCtrl item reference, and then pass this info to
the message window.
Message window wxTreeCtrl: Item
^ | EVT_TREE_
Data | | SEL_CHANGED
------ Main window <-------
However, I would rather not have the main window worry
about the details of how the data is stored in the
wxTreeCtrl. Therefore I would like to capture the
event within the wxTreeCtrl object, and subsequently
send out a custom event that contains the data in a
simple, restructured format (e.g. as a list or a
simple dictionary).
Item
> EVT_TREE_
> SEL_CHANGED
v
Message window wxTreeCtrl: Item
^ | CUSTOM
Data | | EVENT
------ Main window <------- with Data
By looking through the documentation, I haven't found
a way to attach custom data structures to events. Is
it possible? Or is there a semi-elegant workaround?
I hope my problem description made some sense. Any
pointers would be appreciated.
Events are associated in wxPython with the Python objects that wrap the underlying C objects, just write an initialiser that stores the data (and a Clone method that copies it). See below for an example (this is actually auto-generated code from wxoo, btw):
ID_VALUECHANGED = wx.NewEventType()
def EVT_VALUECHANGED( window, id=-1, function=None, disconnect=0 ):
"Bind a handler for a ValueChangedEvent"
if disconnect:
window.Disconnect( id, id, ID_VALUECHANGED, function )
else:
window.Connect( id, id, ID_VALUECHANGED, function )
class ValueChangedEvent(wx.PyCommandEvent):
"""The value being edited by a window has changed
Attributes:
object -- the new object
previousObject -- the previous value (or None)
"""
eventType = ID_VALUECHANGED
def __init__( self, windowID, object=None, previousObject=None):
wx.PyCommandEvent.__init__( self, self.eventType, windowID )
self.object, self.previousObject = object, previousObject
def Clone( self ):
"Return a copy of this event"
return self.__class__( self.GetId(), self.object, self.previousObject )
thanks a lot for your prompt reply. I think I almost
got it to work: I defined the event and bound it to a
callback function just as in your example. I sent the
event off using the wxEventHandler.AddPendingEvent()
method. So far, so good. However, in the callback
function the event arrives as an object of type
wxCommandEventPtr! And the wxCommandEventPtr class
doesn't know anything of my custom data attributes, of
course.
Do I have to define a MyCustomEventPtr class somehow?
Or should I use a different method to send the event
off?
TIA
Klaus
···
--- "Mike C. Fletcher" <mcfletch@rogers.com> wrote:
Events are associated in wxPython with the Python
objects that wrap the
underlying C objects, just write an initialiser that
stores the data
(and a Clone method that copies it). See below for
an example (this is
actually auto-generated code from wxoo, btw):
ID_VALUECHANGED = wx.NewEventType()
def EVT_VALUECHANGED( window, id=-1, function=None,
disconnect=0 ):
"Bind a handler for a ValueChangedEvent"
if disconnect:
window.Disconnect( id, id, ID_VALUECHANGED,
function )
else:
window.Connect( id, id, ID_VALUECHANGED,
function )
class ValueChangedEvent(wx.PyCommandEvent):
"""The value being edited by a window has
changed
Attributes:
object -- the new object
previousObject -- the previous value (or
None)
"""
eventType = ID_VALUECHANGED
def __init__( self, windowID, object=None,
previousObject=None):
wx.PyCommandEvent.__init__( self,
self.eventType, windowID )
self.object, self.previousObject = object,
previousObject
def Clone( self ):
"Return a copy of this event"
return self.__class__( self.GetId(),
self.object,
self.previousObject )
Actually, not quite "of course" . At least up to wxPython 2.5.1.5, there was a mechanism called "original object return" that *should* result in the original Python object showing up whenever the C-level object is passed into Python. That works (at least in my code) fine with this code to send the events:
index = event.GetSelection()
for event in (
events.ObjectChoiceEvent(
self.GetId(),
self.GetValue( index = index),
index,
self._objects
),
events.ValueChangedEvent(
self.GetId(),
self.GetValue( index = index),
)
):
event.SetEventObject( self )
self.GetEventHandler().AddPendingEvent( event )
with the resulting events including the extra attributes I've added AFAICS.
Good luck,
Mike
···
kavaumail-wxpython@yahoo.com wrote:
Mike,
thanks a lot for your prompt reply. I think I almost
got it to work: I defined the event and bound it to a
callback function just as in your example. I sent the
event off using the wxEventHandler.AddPendingEvent()
method. So far, so good. However, in the callback
function the event arrives as an object of type
wxCommandEventPtr! And the wxCommandEventPtr class
doesn't know anything of my custom data attributes, of
course.
Working on my first wxpython program on Windows. I have a couple of TextCtrls and some buttons at the bottom. I wanted to have a panel containing TextCtrls within a frame so I could tab between TextCtrls but my buttons needed to be in the frame so they could close it. The EVT_TEXT_ENTER events of the TextCtls control whether the ok button is enabled. And in turn, the function called from the ok button refers to the values of the TextCtrls. As it stands now, I could not use a panel cause I could not figure out how to reference the buttons from the EVT_TEXT_ENTER event and vice versa. Does that make any sense? I know its an easy answer but like I said, I'm just gittin started.
You can either save a reference to the buttons somewhere that you can reach later when you need them, or you can find the objects when you need them using parentWindow.FindWindowById(theID).
···
--
Robin Dunn
Software Craftsman http://wxPython.org Java give you jitters? Relax with wxPython!
Actually, not quite "of course" . At least up to wxPython 2.5.1.5, there was a mechanism called "original object return" that *should* result in the original Python object showing up whenever the C-level object is passed into Python. That works (at least in my code) fine with this code to send the events:
OOR is not set up for the event classes, they don't have the right base class to support it.
···
--
Robin Dunn
Software Craftsman http://wxPython.org Java give you jitters? Relax with wxPython!
michael montagne wrote:
> Working on my first wxpython program on Windows. I have a couple of
> TextCtrls and some buttons at the bottom. I wanted to have a panel
> containing TextCtrls within a frame so I could tab between TextCtrls but
> my buttons needed to be in the frame so they could close it. The
> EVT_TEXT_ENTER events of the TextCtls control whether the ok button is
> enabled. And in turn, the function called from the ok button refers to
> the values of the TextCtrls. As it stands now, I could not use a panel
> cause I could not figure out how to reference the buttons from the
> EVT_TEXT_ENTER event and vice versa. Does that make any sense? I know
> its an easy answer but like I said, I'm just gittin started.
You can either save a reference to the buttons somewhere that you can
reach later when you need them, or you can find the objects when you
need them using parentWindow.FindWindowById(theID).
And if you don't like idea to using IDs, then you can try to locate controls
using their names or even labels (FindWindowByName,FindWindowByLabel). Just
give some "meaningful" name to control upon the creation (using the "name"
parameter) and then use global function wx.FindWindowByName(
<your-control-name> ) lately to locate it. Personally I found this is the
easiest way to handle GUI things because you don't need to know/remember how
and there controls are created and there you can get a references to them.