Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: Python: Python

OOP Newbie mixing COM, wxPython, BOA

 

 

Python python RSS feed   Index | Next | Previous | View Threaded


mojo at geofinity

Feb 10, 2002, 11:03 AM

Post #1 of 3 (377 views)
Permalink
OOP Newbie mixing COM, wxPython, BOA

The subject line could easily have been "fool in way over his head..."

That said, I got farther than I thought possible only to be stymied by what
I'd guess is either an idiom I don't understand (being an OOP newbie) or a
question of variable scope/namespace...

My problem is that my app has two classes (a class encapsulating the GUI,
and a class that implements an event handler for a COM object.) I don't
know how to access GUI objects in the former, from code in the latter.

I've built a GUI using the latest BOA Constructor (very nice), wxPython
(2.3.2.1) on Python 2.1.1 (ActiveState). The GUI runs nicely, and is
encapsulated in a nifty class I named "VpFrame". VpFrame includes a menu
with event bindings to internal (VpFrame) methods, and a tree widget. The
tree widget is created inside a VpFrame method named "_init_ctrls__" using
the command:

self.buddyTree = wxTreeCtrl(id = wxID_VPFRAMEBUDDYTREE, name = 'buddyTree',
parent = self.mainSplit, pos = wxPoint(354, 2), size = wxSize(157, 407),
style = wxTR_HAS_BUTTONS, validator = wxDefaultValidator)

Next, I used win32com to add access to the JabberCOM object and created a
class to process events coming from the COM object. This event processing
class is called and "JabberEvents" and works also. My menu from VpFrame
successfully executes a "Connect" method via the JabberCOM object. This
object, in turn, sends a message to the remote server (verified) and
receives an "OnConnect" event (verified) from the server. I know that
"JabberEvents" is working because it's "OnConnect" event handler contains
the code that makes my "presence" visible to other users of the server.
Only when this event is processed do I become "Online" to other users. I've
verified that all of this works simply by logging in (as a different user,
on a different machine) and watching for my presence to appear. It does.

My next step is to add code to the "OnConnect" event handler (in the
"JabberEvents" class) that adds some items (e.g. my list of buddies) to the
tree object in VpFrame. This is where I'm stumped. For code inside the
VpFrame class, I can simply call "self.buddyTree.AddRoot("Root Item On
Tree") and it works. Unfortunately none of my (scattershot) attempts to do
this from the JabberEvents class work. I've tried "buddyTree.AddRoot" (no
global attribute named "buddyTree"), "VpFrame.buddyTree.AddRoot" (class
VpFrame has no attribute 'buddyTree'), etc. I also tried creating a method
inside the VpFrame class (FillTree()) to do the tree management. I can call
this method from the menu (self.FillTree() inside the VpFrame class) but not
from code in the JabberEvents class.

How do I call the "AddRoot" method of the "buddyTree" object in the VpFrame
class, from the separate class "JabberEvents"? Any help, pointers,
explanations greatly appreciated. I've include the code (trimmed as much as
possible for brevity) below.

Thanks,

David
---
--
-


######### Code For "vp.py" #########
from wxPython.wx import *
import VpFrame
modules ={'VpFrame': [1, 'Main frame of Application', 'VpFrame.py']}

class BoaApp(wxApp):
def OnInit(self):
self.main = VpFrame.create(None)
self.main.Show(true)
self.SetTopWindow(self.main)
return true

def main():
application = BoaApp(0)
application.MainLoop()

if __name__ == '__main__':
main()

######### Code For "VpFrame.py" #########
def create(parent):
return VpFrame(parent)

[wxID_VPFRAME, wxID_VPFRAMEBUDDYTREE, wxID_VPFRAMEMAINSPLIT] = map(lambda
_init_ctrls: wxNewId(), range(10))

class JabberEvents:
"""Main handler for Jabber events"""

def OnConnect(self):
"""Event occurs when a sucessfull connection to the Jabber server is
established"""
jab.Available = 1
jabRoster.Fetch()
try:
VpFrame.buddyTree.AddRoot('This is some text')
except:
TBStrings = traceback.format_exception(*sys.exc_info())
for Line in TBStrings:
print Line

jab = win32com.client.DispatchWithEvents("JabberCOM.JabberSession",
JabberEvents)
jabRoster = jab.Roster

[wxID_WXFRAME1FILEMENUITEMS0, wxID_WXFRAME1FILEMENUITEMS1,
wxID_WXFRAME1FILEMENUITEMS2, wxID_WXFRAME1FILEMENUITEMS3] = map(lambda
_init_coll_FileMenu_Items: wxNewId(), range(4))

class VpFrame(wxFrame):
""" Main Application "Frame", provides the (GUI) user interface"""

def _init_coll_menuBar1_Menus(self, parent):
parent.Append(menu = self.FileMenu, title = 'File')

def _init_coll_FileMenu_Items(self, parent):
parent.Append(checkable = false, helpString = 'Connect to the VP
System', id = wxID_WXFRAME1FILEMENUITEMS0, item = 'Connect')
parent.Append(checkable = false, helpString = 'Disconnect from the
VP system', id = wxID_WXFRAME1FILEMENUITEMS1, item = 'Disconnect')
parent.Append(checkable = false, helpString = 'Exit VP', id =
wxID_WXFRAME1FILEMENUITEMS3, item = 'Exit')
EVT_MENU(self, wxID_WXFRAME1FILEMENUITEMS0, self.OnFileMenuConnect)
EVT_MENU(self, wxID_WXFRAME1FILEMENUITEMS1,
self.OnFileMenuDisconnect)
EVT_MENU(self, wxID_WXFRAME1FILEMENUITEMS3, self.OnFileMenuExit)

def _init_utils(self):
self.FileMenu = wxMenu(title = '')
self._init_coll_FileMenu_Items(self.FileMenu)
self.menuBar1 = wxMenuBar()
self._init_coll_menuBar1_Menus(self.menuBar1)

def _init_ctrls(self, prnt):
wxFrame.__init__(self, id = wxID_VPFRAME, name = '', parent = prnt,
pos = wxPoint(367, 442), size = wxSize(521, 485), style =
wxDEFAULT_FRAME_STYLE, title = 'VP Version 3.0')
self._init_utils()
self.SetClientSize(wxSize(513, 451))
self.SetMenuBar(self.menuBar1)

self.mainSplit = wxSplitterWindow(id = wxID_VPFRAMEMAINSPLIT, name =
'mainSplit', parent = self, point = wxPoint(0, 0), size = wxSize(513, 412),
style = wxSP_3D)
self.mainSplit.SetMinimumPaneSize(100)
self.mainSplit.SetSashSize(4)

self.buddyTree = wxTreeCtrl(id = wxID_VPFRAMEBUDDYTREE, name =
'buddyTree', parent = self.mainSplit, pos = wxPoint(354, 2), size =
wxSize(157, 407), style = wxTR_HAS_BUTTONS, validator = wxDefaultValidator)
self.buddyTree.SetToolTipString('Buddy Tree')
self.mainSplit.SplitVertically(self.mainNote, self.buddyTree, 350)

self._init_coll_mainNote_Pages(self.mainNote)

def __init__(self, parent):
self._init_ctrls(parent)

def FillTree(self):
myStat = "My Roster (" + `jabRoster.Count` + ")"
btRoot = self.buddyTree.AddRoot(myStat)
btOnline = self.buddyTree.AppendItem(btRoot, 'Online Buddies')
btOffline = self.buddyTree.AppendItem(btRoot, 'Offline Buddies')
self.buddyTree.Expand(btRoot)
self.buddyTree.Expand(btOnline)
self.buddyTree.Expand(btOffline)

def OnFileMenuConnect(self, event):
jab.Username = 'userid'
jab.Password = 'password'
jab.Resource = 'resname'
jab.Server = 'servername'
jab.Port = 'portnum'
jab.DoConnect(0,5)

def OnFileMenuExit(self, event):
self.Close()

def OnFileMenuDisconnect(self, event):
jab.DoDisconnect(1)


jeff at ccvcorp

Feb 11, 2002, 6:29 PM

Post #2 of 3 (344 views)
Permalink
OOP Newbie mixing COM, wxPython, BOA [In reply to]

Mojo wrote:

> The subject line could easily have been "fool in way over his head..."
>
> That said, I got farther than I thought possible only to be stymied by what
> I'd guess is either an idiom I don't understand (being an OOP newbie) or a
> question of variable scope/namespace...
>
> My problem is that my app has two classes (a class encapsulating the GUI,
> and a class that implements an event handler for a COM object.) I don't
> know how to access GUI objects in the former, from code in the latter.

....

> How do I call the "AddRoot" method of the "buddyTree" object in the VpFrame
> class, from the separate class "JabberEvents"? Any help, pointers,
> explanations greatly appreciated.

This is pretty much a namespace issue, and has nothing to do with COM, and only
indirectly with wxPython/Boa...

What you should do, is instead of making the Jabber object be global to your
VpFrame module, you should encapsulate its creation into a function. Have your
frame call this function in its __init__(), and then save the reference on the
frame. At this point, you will also want to stick a reference to the frame onto
the Jabber object. Something like this:

def InitializeJabber():
jab = win32com.client.DispatchWithEvents("JabberCOM.JabberSession",
JabberEvents)
return jab

## in class VpFrame...
...
def __init__(self, parent):
self._init_ctrls(parent)
self.jabber = InitializeJabber()
self.jabroster = self.jabber.Roster
self.jabber.frame = self

Note that you'll need to change all your references to 'jab' and 'jabroster' to
use this saved reference.

Now, in any of your Jabber object's methods, you can do

self.frame.MyFrameEventHandler(mydata)

A few design tips to keep in mind--you want to have the minimum possible number
of connections between your frame and the jabber object. Don't have the jabber
object do each step needed when you connect, for instance; write a VpFrame
method called OnConnect() that handles everything the GUI needs to do, and have
jabber call that single method. Similarly for any other events that you receive
from Jabber--the Jabber object handles the protocol side of things, and then
tells the frame object to handle the GUI side of things. In fact, you might
look at defining custom wxPython command events, and having the Jabber object
notify the GUI by posting those events. (This is a somewhat advanced subject,
which essentially does the same thing--calls a specified method--but allows the
GUI side a lot more flexibility in determining where and how to handle the
event. This could really pay off, though, if you're intending on expanding the
application considerably.)

Also, by having both objects holding references to each other, we've created a
reference cycle. Python's garbage collector should be able to handle this okay,
but just in case, it's probably a good idea to explicitly destroy the Jabber
object in your frame's OnCloseWindow() handler (or whatever name is given to the
method that shuts down your frame). But it's a common idiom in wxPython for
parent and child windows to each have references to the other. (Typically, the
wxWindows framework will clean up child windows for you, but obviously wxWindows
knows nothing of your Jabber object...)

Jeff Shannon
Technician/Programmer
Credit International


mojo at geofinity

Feb 12, 2002, 8:10 PM

Post #3 of 3 (345 views)
Permalink
OOP Newbie mixing COM, wxPython, BOA [In reply to]

"Jeff Shannon" <jeff[at]ccvcorp.com> wrote in message
news:3C687007.4ACF94EE[at]ccvcorp.com...
<snip>
> What you should do, is instead of making the Jabber object be global to
your
> VpFrame module, you should encapsulate its creation into a function. Have
your
> frame call this function in its __init__(), and then save the reference on
the
> frame. At this point, you will also want to stick a reference to the
frame onto
> the Jabber object.

Yep, that did it. I kept thinking of the Jabber Object as a literal COM
object and immutable (interfaces as API). It might never have dawned on me
that it was actually a python object, and that I could add an attribute at
runtime. Once my head stopped spinning, it made perfect sense. Thanks a
bunch!

<snip>
>... In fact, you might
> look at defining custom wxPython command events, and having the Jabber
object
> notify the GUI by posting those events. (This is a somewhat advanced
subject,

I've got some basic functionality to test first, but that is exactly what I
want to try next.

>
> Also, by having both objects holding references to each other, we've
created a
> reference cycle. Python's garbage collector should be able to handle this
okay,
> but just in case, it's probably a good idea to explicitly destroy the
Jabber
> object in your frame's OnCloseWindow() handler (or whatever name is given
to the
> method that shuts down your frame). But it's a common idiom in wxPython
for
> parent and child windows to each have references to the other.
(Typically, the
> wxWindows framework will clean up child windows for you, but obviously
wxWindows
> knows nothing of your Jabber object...)
>

Will do. I appreciate the advice and explanations. Now, I'm off to make a
bigger mess...

Thanks again,

David
---
--
-

Python python RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact lists@gossamer-threads.com
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.