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
>
>
>

Reply via email to