win98se, Python 2.2.1, wxPython 2.3.2.1 (or 2.3.3pre5)
Hi all,
Writing an interactive interpreter is very instructive.
I programmed a few things that are not working, I do not
understand why, but there are also other thinks that are
working and I do not understand why! Two case studies.
1) Calling a full application from the interpreter (PyCrust or psi)
Assume a full/standalone application in a module called mod.py
having the following skeleton:
···
#-------------------------------------------------------------------
class MyFrame(...)
def __init__(self, parent, id):
...
EVT_CLOSE(self, self.OnCloseWindow)
def OnCloseWindow(self, event):
print 'OnCloseWindow'
self.Destroy()
class MyApp(wxApp):
def OnInit(self):
frame = MyFrame(NULL, -1)
frame.Show(true)
self.SetTopWindow(frame)
return true
def main():
print 'main is running...'
app = MyApp(0)
app.MainLoop()
if __name__ == "__main__" :
main()
#-------------------------------------------------------------------
Now, in the interpreters (psi or PyCrust) I can
import mod
mod.main()
and the application start correctly.
The problem is raising when I close the application. In PyCrust,
closing the application will close PyCrust too. In psi, where the
interpreter class is a little bit different, the application closes,
but not psi. In that case, the application seems still 'pending' and
I can no more use psi. I looks like if the python interpreter has not
finished its jobs.
Has this to do with a "ThreadedInterpreter"? Two MainLoops running
at the same time? ... Why can I not start the application with
sys.execfile('mod.py')? Should the application returns some
flags? ...
2) Modules using wxPython
PyCrust or psi being interactive interpreters based on wxPython,
it should be (and it is) possible to import modules using wxPython.
For tests, I wrote the following module, job.py
#-------------------------------------------------------------------
#just draw an x,y fuction to do something interesting
from wxPython.wx import *
def MyScaleXY(w1x, w1y, w2x, w2y, ux, uy, u1x, u1y, u2x, u2y):
wx = (ux - u1x) / (u2x - u1x) * (w2x - w1x) + w1x
wy = (uy - u1y) / (u2y - u1y) * (w2y - w1y) + w1y
return (wx, wy)
class MyDialog1(wxDialog):
def __init__(self, parent, id, xx, yy):
wxDialog.__init__(self, parent, id, "x, y plot", wxPoint(50,50),
wxSize(300, 200))
self.size = self.GetClientSize()
self.plotarea = wxWindow(self, id, wxPoint(0, 0),
self.GetClientSize(), wxNO_BORDER)
self.plotarea.SetBackgroundColour(wxWHITE)
EVT_PAINT(self, self.OnPaint)
EVT_CLOSE(self, self.OnCloseWindow)
self.xx, self.yy = xx, yy
def OnPaint(self, event):
dc = wxPaintDC(self.plotarea)
dc.BeginDrawing()
dc.Clear()
dc.SetPen(wxPen(wxRED))
xmin, xmax = min(self.xx), max(self.xx)
ymin, ymax = min(self.yy), max(self.yy)
if ymin == ymax:
ymin, ymax = ymin - 1., ymax + 1.
if xmin == xmax:
xmin, xmax = xmin - 1., xmax + 1.
p1x, p2x = 0, self.size[0] - 1
p1y, p2y = 0, self.size[1] - 1
#first point
ax, ay = MyScaleXY(p1x, p1y, p2x, p2y, \
self.xx[0], self.yy[0], xmin, ymax, xmax, ymin)
#other points
for i in range(1, len(self.xx)):
bx, by = MyScaleXY(p1x, p1y, p2x, p2y, \
self.xx[i], self.yy[i], xmin, ymax, xmax, ymin)
dc.DrawLine(ax, ay, bx, by)
ax, ay = bx, by
#end of last line
dc.DrawPoint(bx, by)
dc.EndDrawing()
def OnCloseWindow(self, event): # X button
print 'OnCloseWindow'
#~ self.Destroy()
self.EndModal(wxID_CANCEL)
def drawxy(xx, yy):
c = MyDialog1(None, -1, xx, yy)
c.ShowModal()
#------------------------------------------------------
In the interpreters (PyCrust of psi):
x = [0.0, 1.0, 2.0, 3.0, 4.0]
y = [0.0, 1.0, 5.0, 3.0, 4.0]
import job
job.drawxy(x, y)
(then close the window with the X-button)
print 'ok'
ok
I am surprised that job.drawxy(...) is working (the curved is correctly
drawn), the 'parent' of MyDialog1 being None ! Nevetheless, if I move
the opened dialog window, psi or PyCrust (or the underlying
wxStlyledTextCtl) is becoming completely grey. After having
closed the window, everything is ok and I may keep on
working with the interpreter.
The same happens, if
x = [0.0, 1.0, 2.0, 3.0, 4.0]
y = [0.0, 1.0, 5.0, 3.0, 4.0]
import job
c = MyDialog1(None, -1, x, y)
c.ShowModal()
I have the feeling, this happens because the dialog window is not
properly 'hooked' to the interpreter window/frame. Is there a way to
'hook' dynamically a window to the intepreter? Should the interpreter
provide something like an handle for the parent frame?
I agree a standalone application for drawing data is much better, but
playing with python is so nice...
A few words of explanation are welcome.
Jean-Michel Fauth, Switzerland