Introduction to JyScript
JyScript
home page: download, installation instructions and tutorial
We'll start to make illustrations that respond to our requests
for changes.
Drawing a box
| |
PiScript code:
beginpage()
center()
scale(50)
newpath()
box(-1, -1, 2, 2)
setlinewidth(2)
fill(0, 0, 1)
stroke()
endpage()
|
In JyScript, the drawing commands go into a function.
def draw():
beginpage()
center()
scale(50)
newpath()
box(-1, -1, 2, 2)
setlinewidth(2)
stroke([1, 0, 0])
endpage()
|
Originally, the unit in the coordinate system is one pixel.
Now we ask a new window, which will contain our figure, to pop
up by specifying the dimensions of the window and the drawing
function.
openframe(200, 200, draw)
|
Finally, be sure to import JyModule.
Here's the whole thing:
from JyModule import *
def draw():
beginpage()
center()
scale(50)
newpath()
box(-1, -1, 2, 2)
setlinewidth(2)
fill(0, 0, 1)
stroke()
endpage()
openframe(200, 200, draw)
|
If this program is in the file Box.py, it may be run
by typing jython Box.py on the command line.
To create other figures, we simply rewrite the draw
function.
Notice that there is no init or finish
as there is in PiScript.
|
Moving a box
| |
We'll add a button that moves the box to the right when
pressed.
First, we'll add a variable x, which keeps
track of where to draw the box.
x = -1
def draw():
beginpage()
center()
scale(50)
box(x, -1, 2, 2)
fill(0, 0, 1)
stroke()
endpage()
|
We need to define a function that will be called when the button
is pressed. Since we are changing the value of the variable, we need
to declare it to be global. Also, we need to call
refresh so that our changes appear.
def step():
global x
x += 0.1
refresh()
|
Finally, we add the button, specifying a string to display on the
button and a function to call when pressed.
Here is the program in its entirety.
from JyModule import *
x = -1
def draw():
beginpage()
center()
scale(50)
box(x, -1, 2, 2)
fill(0, 0, 1)
stroke()
endpage()
def step():
global x
x += 0.1
refresh()
addbutton("Move", step)
openframe(200, 200, draw)
|
It is important to add any buttons before opening the frame.
|
Adding a reset button
| |
After we press the button a few times, it disappears from our
frame. We will therefore add a button to restore the original
configuration.
def reset():
global x
x = -1
refresh()
addbutton("Reset", reset)
|
The entire program is here:
from JyModule import *
x = -1
def draw():
beginpage()
center()
scale(50)
box(x, -1, 2, 2)
fill(0, 0, 1)
stroke()
endpage()
def step():
global x
x += 0.1
refresh()
addbutton("Move", step)
def reset():
global x
x = -1
refresh()
addbutton("Reset", reset)
openframe(200, 200, draw)
|
|
Animations
| |
If pressing that button is wearing you out, you may create an
animation to move the box.
We do this by creating a timer that calls a function at regular
intervals.
def step():
global x
x += 0.02
refresh()
settimer(25, step)
|
The argument 25 sets the interval, in milliseconds,
at which the timer calls the function.
Now we need to add some buttons to control the timer. The
functions starttimer() and stoptimer(),
well, start and stop the timer.
def begin():
starttimer()
addbutton("Start", begin)
def pause():
stoptimer()
addbutton("Stop", pause)
def reset():
global x
stoptimer()
x = -1
refresh()
addbutton("Reset", reset)
|
The whole progam is like this:
from JyModule import *
x = -1
def draw():
beginpage()
center()
scale(50)
box(x, -1, 2, 2)
fill(0, 0, 1)
stroke()
endpage()
def step():
global x
x += 0.02
refresh()
settimer(25, step)
def begin():
starttimer()
addbutton("Start", begin)
def pause():
stoptimer()
addbutton("Stop", pause)
def reset():
global x
stoptimer()
x = -1
refresh()
addbutton("Reset", reset)
openframe(200, 200, draw)
|
The next example shows how to use an animation to fade an element
into the figure, a useful technique in, say, illustrating
proofs.
First, we'll create a variable that controls the transparency of
the blue square.
alpha = 0
def draw():
beginpage()
center()
scale(50)
setlinewidth(2)
newpath()
box(-2, -2, 4, 4)
fill(1,0,0)
stroke()
gsave()
setcomposite(alpha)
newpath()
circle(1, 1, 1.5)
fill(0, 0, 1)
stroke()
grestore()
endpage()
|
Now set the timer
def step():
global alpha
alpha += 0.01
if alpha > 1:
alpha = 1
stoptimer()
refresh()
settimer(25, step)
|
and add the buttons.
def begin():
starttimer()
def pause():
stoptimer()
def reset():
global alpha
stoptimer()
alpha = 0
refresh()
addbutton("Start", begin)
addbutton("Stop", pause)
addbutton("Reset", reset)
|
All together:
from JyModule import *
alpha = 0
def draw():
beginpage()
center()
scale(50)
setlinewidth(2)
newpath()
box(-2, -2, 4, 4)
fill(1,0,0)
stroke()
gsave()
setcomposite(alpha)
newpath()
circle(1, 1, 1.5)
fill(0, 0, 1)
stroke()
grestore()
endpage()
def step():
global alpha
alpha += 0.01
if alpha > 1:
alpha = 1
stoptimer()
refresh()
settimer(25, step)
def begin():
starttimer()
def pause():
stoptimer()
def reset():
global alpha
stoptimer()
alpha = 0
refresh()
addbutton("Start", begin)
addbutton("Stop", pause)
addbutton("Reset", reset)
openframe(300, 300, draw)
|
|
Moveablepoints
| |
For a final kind of interactivity, we'll add points that may
be moved by clicking and dragging.
We do this using a Moveablepoint. First, we create
the point by specifying its coordinates and a function to be called
when the point is moved. We also register this point using the
addmoveable function.
def move(point, x, y):
point.setpoint(x, -1)
movingpoint = Moveablepoint(-1, -1, move)
addmoveable(movingpoint)
|
We can use the point's coordinates in our draw method. Also, the
point is drawn using the placemoveable function. The
point's coordinates are interpreted relative to the current coordinate
system when placemoveable is called.
def draw():
beginpage()
center()
scale(50)
newpath()
box(movingpoint.x, -1, 2, 2) # <-----
setlinewidth(2)
fill(0, 0, 1)
stroke()
newpath()
placemoveable(movingpoint) # <-----
endpage()
|
The whole program looks like:
from JyModule import *
def draw():
beginpage()
center()
scale(50)
newpath()
box(movingpoint.x, -1, 2, 2)
setlinewidth(2)
fill(0, 0, 1)
stroke()
newpath()
placemoveable(movingpoint)
endpage()
def move(point, x, y):
point.setpoint(x, -1)
movingpoint = Moveablepoint(-1, -1, move)
addmoveable(movingpoint)
openframe(200, 200, draw)
|
This is a little more involved so here is a summary:
- Create a function to be called when the point is moved.
- Create the point, specifying its coordinates and the function.
- Register the point with
addmoveable
- Draw the point with
placemoveable
- Use the point's coordinates in the drawing function.
We may have any number of Moveablepoints.
from JyModule import *
def draw():
beginpage()
center()
scale(50)
newpath()
dx = upperright.x - lowerleft.x
dy = upperright.y - lowerleft.y
box(lowerleft.x, lowerleft.y, dx, dy)
setlinewidth(2)
fill(0, 0, 1)
stroke()
newpath()
placemoveable(lowerleft)
placemoveable(upperright)
endpage()
def move(point, x, y):
point.setpoint(x, y)
lowerleft = Moveablepoint(-1, -1, move)
upperright = Moveablepoint(1, 1, move)
addmoveable(upperright)
addmoveable(lowerleft)
openframe(200, 200, draw)
|
Moveablepoints have many attributes that may be set.
setstyle |
'circle' or Moveablepoint.CIRCLE,
'square' or Moveablepoint.SQUARE,
'diamond' or Moveablepoint.DIAMOND
|
setfillcolor |
a color |
setstrokecolor |
a color |
setsize |
a float |
setstrokesize |
a float |
setfilled |
True,
False |
setstroked |
True,
False |
listentoclicksonly |
True,
False |
Another example
from JyModule import *
x = 1
y = 1
def draw():
beginpage()
scale(10)
newpath()
placemoveable(point)
newpath()
string = 'Mouse at (%.1f, %.1f)' % (x, y)
setfont(30)
moveto(4, 9)
show(string)
endpage()
def move(point, px, py):
global x, y
x, y = px, py
point = Moveablepoint(1, 1, move)
point.setsize(400)
point.setfilled(False)
point.setstroked(False)
addmoveable(point)
openframe(400, 200, draw)
|
|
Multiple figures
| |
Using these ideas, we may create dynamic illustrations with
multiple figures.
from JyScript import *
t = -1
def draw(p):
...
def clock(p):
...
def step():
global t
t += 0.02
if t > 1:
t = 1
stoptimer()
refresh()
settimer(25, step)
def begin():
starttimer()
def pause():
stoptimer()
def reset():
global t
t = -1
stoptimer()
refresh()
addbutton("Start", begin)
addbutton("Stop", pause)
addbutton("Reset", reset)
openframe({'c': [200, 200, draw], 's': [200, 20, clock]})
|
|
|