This example demonstrates the use of PyEval()
in UIL to
evaluate a string that invokes a callback. If the callback were
"pre-defined", then a UIL-writer would not have to write any Python
code to use this technique, other than the string passed to
PyEval()
to evaluate.
There are three files required--a .uil file named button2.uil, a .uid file named button2.uid, and a Python script named testbutton2.py.
button2.uil contains the following text:
module button_test_2 version = 'V1.0' names = case_sensitive procedure PyEval(string); ! declare PyEval object main : XmBulletinBoard { ! bulletin board parent arguments { XmNwidth = 200; XmNheight = 200; }; controls { XmPushButton button; ! main is parent of button }; }; object button : XmPushButton { ! button is labelled Push Me arguments { XmNx = 0; XmNy = 0; XmNwidth = 100; XmNheight = 40; XmNlabelString = 'Push Me'; }; callbacks { XmNactivateCallback = procedure PyEval("MyPrint(g_var)"); }; }; end module;
button2.uid is created by the uil compiler as noted in the first example.
testbutton2.py (which must have execute permission) contains the following left-justified text:
#!/usr/local/bin/python import os, sys, Mrm, Xt def MyPrint(msg): # MyPrint is defined in __main__ print msg def main(): global g_var # g_var has global scope in __main__ g_var = 'a global value' print 'g_var =',g_var top_level = Xt.Initialize() # fetch the hierarchy mrm_hier = Mrm.OpenHierarchy('button2.uid') main_w = mrm_hier.FetchWidget('main', top_level) # manage widgets, realize shell main_w.ManageChild() top_level.RealizeWidget() Xt.MainLoop() main()
The script is executed by the statement:
testbutton2.py
When executed, the testbutton2.py script first declares the function
MyPrint()
. MyPrint()
is in the scope of the Python
"unnamed" module __main__
because no other module was named for
MyPrint()
to be in the scope of. This is an important point,
because PyEval
evaluates its string in this namespace, and so
can find MyPrint()
.
Then the script declares the function main()
. main()
declares the global g_var
. g_var
is also in the
__main__
namespace, for the same reason as MyPrint()
.
g_var
is defined in this namespace so that it can be used in
the tag argument of the PyEval
call. The script opens the
hierarchy defined by button.uid, fetches the widget named "main",
which is a bulletin board, and its child, a pushbutton, manages these
widgets and realizes the shell, and enters the Xt Event Loop.
Finally, the script invokes the main()
function, which executes
the code and builds the interface.
When the user pushes the pushbutton (labelled "Push Me" in the .uil
file), the PyEval()
function is called with the string
"MyPrint(g_var)". This string is evaluated by Python in the context
of module __main__
, and calls MyPrint()
passing as the
argument the variable g_var
. MyPrint()
simply prints
it's argument's value, which is that of g_var
--"a global
value".
Note that if the testbutton2.py script was imported, then
MyPrint()
would not be in __main__
namespace.
testbutton2.py could be imported by the statement:
import testbutton2
In this case, MyPrint
and g_var
would be globals in the
module testbutton2's namespace; and so the .uil file would have to be
coded differently to invoke MyPrint()
, as shown below:
callbacks { XmNactivateCallback = procedure PyEval( "import testbutton2; testbutton2.MyPrint(testbutton2.g_var)"); };