Just to follow up on how I solved my problem, here is what I did.
I have files, script_launcher.py, controller.py, view.py, model.py which implement a classic model view controller interface. I can install this "Special Wizard" by the "Install Plugin..." menu item from the Plugins menu. To call functions in model from View use the cmd.get_wizard() function. Never call functions in View from within the Model Let me know if you are interested in the details. Matt O'Meara UNC Chapel Hill ******************************************** in script_launcher.py I have import controller, view, model def __init__( self ): self.menuBar.addmenuitem('wizard', 'command', 'Special Wizard', label= "Special Wizard", command= lambda s=self: launch( s ) ) def launch( s ): controller = controller.Controller() view = view.View( s, controller ) model = model.Model( controller ) cmd.set_wizard( model ) ***************************************** in controller.py I have class Controller: def __init__( self ): self.handlers = [] self.events = {} #event handling routines ***************************************** in view.py I have class View(): def __init__( self, app, controller ): self.parent = Tkinter.Toplevel( app.root ) self.controller = controller #register event handlers with self.controller self.updater() def updater( self ): #check for events to handle in self.controller self.parent.after( 500, self.updater ) ***************************************** in model.py I have class Model( Wizard ): def __init__( self, controller, _self=cmd ): if _self.__name__ = "pymol.cmd": Wizard.__init__(self, _self ) else: Wizard.__init__(self, _self.cmd ) self.controller = controller #register events with self.controller On Fri, Apr 25, 2008 at 4:15 PM, DeLano Scientific <del...@delsci.info> wrote: > Matt, > > A key PyMOL concept for Tkinter developer to grasp is that Tkinter runs in > a separate thread from PyMOL. Thus, direct calls to Tkinter from a PyMOL > thread will fail erratically, as observed below. > > Fortunately, PyMOL is built so that it can receive API calls asychronously > from any thread. Therefore, you can develop using Tkinter from the its own > thread, and then message PyMOL from there. The only hard part is launching > your GUI, which is something you cannot do from a PyMOL script or program > directly. Instead, you add a new item in the Plugin menu or a whole new > menu for your GUI as part of your initialization. > > The plugin approach is the safe way to add new functionality using > Tkinter. See modules/pmg_tk/startup/__init__.py for example code to get you > started. > > Cheers, > Warren > > -- > DeLano Scientific LLC > Subscriber Support Services > mailto:del...@delsci.info <del...@delsci.info> > > > ------------------------------ > *From:* pymol-users-boun...@lists.sourceforge.net [mailto: > pymol-users-boun...@lists.sourceforge.net] *On Behalf Of *Matthew O'Meara > *Sent:* Friday, April 25, 2008 12:46 PM > *To:* PyMOL-users@lists.sourceforge.net > *Subject:* [PyMOL] access to tkinter root for new Toplevel? > > Hi All, > > I would like to write a Wizard that spawns a separate window. Right now > I'm just calling Tkinter.Toplevel() with no arguments but it dies with > non-deterministic tkinter errors. I think the issue is I need to pass the > Tkinter.Tk() instance into the Toplevel command. > > 1) Is there a way I can get access to the main Tkinter.Tk() instance from > within my Wizard? > > > I've made a simple version of what I would like that shows the behavior I'm > seeing. To run, copy this into a file called testWizard.py and place into > the wizard directory. Since I installed from Distutils on linux, my wizard > directory is /usr/local/lib/python2.5/site-packages/pymol/wizard/. Then > fire up pymol and type into the command line 'wizard testWizard'. If you > version is <1.0 try deleting '_self=cmd' and '_self'. For me it crashes > about every third or so time, usually with different errors. > > > from pymol.wizard import Wizard > from pymol import cmd > import pymol > import Tkinter > > > class TestWizard(Wizard): > > def __init__(self,_self=cmd): > Wizard.__init__(self, _self) > > self.res_table = Tkinter.Tk() # <- pass app.root in here???? > > for i in range( 1000 ): Tkinter.Button(self.res_table, > text=str(i)).pack() > > > Thanks in advance! > Matt > > >