Adding new QScript events
We have seen in the previous guide how to add new functions and to listen for events. In this guide I will demonstrate how to add new scripting events.
We start with the hypot function we created in an earlier guide and we will create a new event to be fired when the hypot function is evaluated.
So the first thing we are going to do is modify the HypotenuseFunction class to fire an event.
The 'hypot' Function that fires an event
Just four additinal lines of code (24 to 27) have been added for the event firing. In most cases this could be simplified because you are most unlikely to be interested in the token's position in the source script also the sixth parameter is optional so the most basic form of line 27 is -
script.fireEvent(HpotCalculatedEvent.class, null, -1, -1, -1);
public static class HypotenuseFunction extends Operator {
public HypotenuseFunction(String symbol, int nbrArgsNeeded, int priority, int type) {
super(symbol, nbrArgsNeeded, priority, type);
}
public Argument resolve(Script script, Token token, Argument[] args, Object... objects)
throws EvaluationException {
testForUninitialisedVars(script, args);
Argument a0 = args[0];
Argument a1 = args[0];
if (a0.isNumeric() && a1.isNumeric()) {
double s0 = a0.toDouble(), s1 = a1.toDouble();
double hyp = Math.sqrt(s0*s0 + s1*s1);
script.fireEvent(HpotCalculatedEvent.class, null, token, new Argument(new Double(hyp)));
return new Argument(new Double(hyp));
}
// If we get here then the arguments are invalid
handleInvalidArguments(script, token);
return null;
}
}
The only difference is the statement at line 15 which is responsible for firing the event.
The fireEvent method has five parameters
No | Value | Description |
---|---|---|
1 | HpotCalculatedEvent.class |
This is the class of the event to be fired |
2 | null | For user defined events this will always be null |
3 | token |
this is the token that is being resolved. |
4 | Object or Object[] | this parameter is optional and can be either a single Oject or an array of Objects. This extra
information will be included in the event which will cast the object(s) back to the correct type.
In this example it is the length of the hypotenuse wrapped into an Argument object.> |
We still have to create the HypotCalculatedEvent class - not much too it really
public static class HpotCalculatedEvent extends ScriptEvent {
public HpotCalculatedEvent(Script script, ErrorType etype, int lineNo, int pos, int width, Object[] extra) {
super(script, etype, lineNo, pos, width, extra);
message = "The hypotenuse has been calculated";
}
public HpotCalculatedEvent(Script script, ErrorType etype, int lineNo, int pos, int width) {
this(script, etype, lineNo, pos, width, null);
}
}
This example (AddingAnEvent) has been included with the library download. The core of the sketch code without the import statements is shown here.
Script script;
float a = 1, b = 1, h = 1;
String stopText = "";
public void setup() {
size(400, 400);
HypotenuseFunction h;
h = new HypotenuseFunction("hypot", 2, 30, Operator.FUNCTION);
OperatorSet.get().addOperator(h);
String[] code = {
"WHILE(true)",
" a = rnd(10, 100)",
" b = rnd(10, 100)",
" h = hypot(a, b)",
" WAIT(rnd(2000, 5000))",
"WEND"
};
script = new Script(code);
// Script events are to be sent to this object
script.addListener(this);
Solver$.evaluate(script);
}
public void keyTyped() {
if (key == 's' || key == 'S')
script.stop();
}
public void draw() {
background(200, 255, 200);
drawTriangle(a, b, h);
fill(0);
if (!script.isStopped()) {
text("WORKING ...", 20, 20);
text("press S to stop", 20, 36);
} else
text(stopText, 20, 20);
}
@EventHandler
public void onScriptEvent(ScriptEvent event) {
if (event instanceof HpotCalculatedEvent) {
a = script.getVariable("a").toFloat();
b = script.getVariable("b").toFloat();
h = ((Argument)event.extra[0]).toFloat();
} else if (event instanceof HaltExecutionEvent) {
stopText = "Program halted";
}
}
public void mouseClicked() {
save("triangle" + millis()%100 + ".png");
}
public void drawTriangle(float a, float b, float h) {
// code omitted for clarity
}
The script will generate two random lengths and calculate the hypotenuse. It will then pause for 3-10 seconds before calculating and drawing the new triangle.

The eventhandler will hear when a hypotenuse is calculated and retrieve the 2 lengths from the script's data store and the hypotenuse from the optional parameter from the event (we could have got it from the data store but this demonstrates the extra parameter on the event).