An event system for Processing 4!

I am back with a better version of event bindings for Processing. This system can be used with Processing 4 and Eclipse. Unfortunately, it cannot be used with Processing 3 because the library requires Java version 8+ for lambdas () -> {} and the double colon operator ::


  • create a final Event.PX<...> onEvent; replace the ... with the parameter types you would like to pass in your event. Now replace the X in PX by the number of arguments you passed, for instance: final Event.P2<Integer, String> onEvent;. To initialize an event use = Event.PX.create() or alternatively = new Event.PX<>() with the X being replaced same as above.
  • create a listener final Listener.PX listener = Object::method; the :: operator is called the method reference operator. You can reference any method you wish to execute when the event triggers. You can also alternetively specify a lambda also called a functional interface () -> {}.
  • bind the listener to the event: onEvent.bind(listener)
  • onEvent.trigger(...) whenever you are are ready

Those are the basics. An example is also introduced to really visualize how it works.


  • Reflectionless implementation of events using functional interfaces and generics
  • Support for double colon operator :: for example this::onSetup
  • Error handeling, for instance parameter check and listener method reference
  • trigger(...)
  • bind(method) / unbind(method) / unbind()
  • bind(method, priority, ignoreCancelled) listener priority and cancel handeling
  • bound(method)
  • cancel() / setCancelled(cancelled) / isCancelled()
  • Event.flush(object) failsafe measure in uncontrolled cases to prevent memory leaks
  • Variable<T> implementation to modify the impact of events
  • Events can pass from 0 to 9 parameters by default, generate more at your needs


In this example, there is a world listening and a player emitting events.

public void setup() {
	World world = new World();

// this object host events
// note that it could also listen to events
public static class Player {
	public final Event.P0 onJump;
	public final Event.P1<Variable<Integer>> onCollect;
	int x, y, points;
	public Player() {
		onJump = Event.P0.create();
		onCollect = Event.P1.create(true);
	public void jump() {
		y += 10;
		// event
	public void collect(int points) {
		Variable<Integer> variable = Variable.of(points);
		// event
		// check if event was cancelled, if not continue the process
		if(!onCollect.isCancelled() && !variable.isNull())
			this.points += points;

// this object listens to the player's events
public static class World {
	public final Listener.P0 onPlayerJump = this::onPlayerJump;
	public final Listener.P1<Variable<Integer>> onPlayerCollect = this::onPlayerCollect;
	public final Listener.P1<Variable<Integer>> onPlayerCollected = this::onPlayerCollected;
	Player player;
	boolean doublePoints;
	boolean noPoints;
	boolean test;
	public World() {
		player = new Player();
		player.onCollect.bind(onPlayerCollect, 0);
		player.onCollect.bind(onPlayerCollected, 1, true);
		// --- playground ---
		doublePoints = true;
		noPoints = true;
	// feedback for when the player jumps
	public void onPlayerJump() {
		System.out.println("Jump! :D");
		// WARNING: this is not allowed. cancel() can only be called:
		// #1 on events that are cancellable: 'Event.PX.create(true)' 
		// #2 inside a listener method, othwerwise will throw an exception
		if(test) player.onJump.cancel();
	// apply no points and double points modifiers to points collected by player
	public void onPlayerCollect(Variable<Integer> points) {
			points.apply((p) -> doublePoints? p * 2 : p);
		System.out.println("[info] applied points modifier");
	// feedback for when the player collects points.
	// two listeners are bound to the same event, but this one
	// has a higher priority so it is executed last showing the final
	// points collected. This will not execute if ignoreCancelled is
	// set to true during binding.
	public void onPlayerCollected(Variable<Integer> points) {
		System.out.println("Player collected " + points.get() + " points!");
	public void flush() {
		// WARNING: will not unbind, the operator :: creates a new immutable reference
		// that's why we kept a final reference Listener for each
		// WARNING: since binding has a reference to the listener's container class method
		// this can cause memory leaks if not used properly
		// in uncontrolled scenarios, this method can be used as a failsafe when you are
		// done with an object.

Source code

This library is hosted on GitHub, add the files, and to your project to use the library.

If you require events that need more than 9 variables, you can execute to expand beyond the limit at your needs.

Good things about this

  • It is not interface based, which almost eliminates boilerplate code
  • It is not reflection based, which makes it a little bit more performant than v1. It does include an alternative reflectionTrigger(...) if needed.
  • You can listen to an event and host an event from anywhere: the main class, in no class, in the same class…
  • Error handling is probably the #1 reason why I decided to make a version 2. Parameters are all checked and listener methods are referenced
  • Added event priority and event cancellation

This is the GitHub repository for the library