You're on the right track. There's no reason for your scene to be a GLEventListener. You could do something like:
public interface Scene
public void render( GLDrawable drawable );
Have one GLEventListener that holds a reference to the current scene object, and just calls scene.render( drawable ) in the display() method. Now drawing a different scene is just a matter of changing the reference to point to a different Scene object, no monkeying with the canvas needed.
As to the problem you were seeing: Almost definitely a threading problem. I would guess that jogl is trying to finish rendering a frame before the new listener is added. However, rendering occurs on the same thread as the timer, and so a deadlock occurs.
JOGL is very strict about it's threading for cross-platform compatibility reasons, and so it's best to just set up your canvas once and then leave it alone.
If you dead-set on what you've got now, try spawning a new thread from the timer and changing the eventlistener in that