Unfortunately, in Applets, init is called after addNotify, but when you run your Applet as a hybrid application, init is called before addNotify.
The AWT/Swing toolkit calls addNotify to create/hook up the peer object. You can thus override the addNotify method, so that when super. addNotify returns, you know your peer is ready to go. AWT/Swing calls addNotify for you the first time the component’s setVisible( true ) or pack() method is called. You should not call addNotify directly yourself. The toolkit calls addNotify only once, even if you setVisible( true ); setVisible( false ); setVisible( true );
You piggyback your initialisation code on addNotify like this:
public void addNotify() { super.addNotify(); offScreenImage = createImage( width, height ); }If you put your Component.createImage code in the constructor, it would sometimes work and sometimes not.
What is going on here? createImage wants to create an image in the native screen format. The only thing that knows which screen and which screen device driver you are using is the peer object in the native GUI. However, the peer does not exist until super.addNotify() returns. If you write an addNotify method that calls super.addNotify, when it returns from super.addNotify, you can rest assured the peer object has been created and it is now safe to call createImage. So you might as well just tuck you code right after the call to super.addNotify and it will automatically be called immediately after the peer object has been created.
One disadvantage to putting initialisation code in addNotify, is that you can’t mark the instance variable that you are initialising final. Java does not know that addNotify will be called only once.
To get an understanding of how this all works, I suggest peppering your code with debugging messages saying things like constructor X started, constructor X ended, addNotify X started, addNotify X ended etc, to understand the very complex flows of control that can happen, especially when you have overridden methods.
Some rules of thumb: addNotify will not be called until after you constructor completes. It will be called as a side effect of a setVisible( true ); This gives you four places you can put initialisation code that will be executed in this guaranteed order.
I was under the delusion that addNotify might be called unpredictably at any time the underlying GUI asynchronously felt ready to display. I did not know if there would be a race between it and method calls just after the constructor. It is all happily predictable.
This inialisation technique only works if super.addNotify exists or the toolkit will never think to call your addNotify method.
Fortunately, your JPanel addNotify method will be called after the addNotify methods of all the Components in your JPanel.
Another similar place to tuck late initialisation code is in the WindowListener.windowOpened method.
/** * Invoked when a window has been opened. */ public void windowOpened ( WindowEvent e ) { // Normally no super.windowOpened call is needed. // This is pure notification. // windowOpened has no duties. getMyInfo(); }
Why is it called addNotify instead of createPeer. Perhaps the hook it creates notifies both Java and the native GUI of interesting events.
Despite its name, addNotify does not get called when the Component is added to a Container. Perhaps it did in the deep past, hence the misleading name.
This page is posted |
http://mindprod.com/jgloss/addnotify.html | |
Optional Replicator mirror
|
J:\mindprod\jgloss\addnotify.html | |
Please read the feedback from other visitors,
or send your own feedback about the site. Contact Roedy. Please feel free to link to this page without explicit permission. | ||
Canadian
Mind
Products
IP:[65.110.21.43] Your face IP:[3.12.123.52] |
| |
Feedback |
You are visitor number | |