Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // ImageRenderer.java
- // SwingEasel
- //
- // Created by Philip Rhodes on 9/2/05.
- // Copyright 2005 Philip J Rhodes. All rights reserved.
- //
- import java.awt.*;
- import java.awt.image.*;
- /** This abstract class provides a VolatileImage for double buffering. Although
- * Swing provides double buffering by default, using a VolatileImage allows
- * the Java Virtual Machine (JVM) to take advantage of hardware acceleration.
- * Even if a particular JVM doesn't do this, or if there is no 3D graphics card
- * installed, there may still be an advantage to using an image, because each
- * drawing operation may be slightly faster.
- */
- public abstract class ImageRenderer extends Renderer{
- protected Image backingImage;
- protected boolean wasPainted = false;
- protected Graphics imageGraphics;
- protected int imageWidth;
- protected int imageHeight;
- protected boolean showFPS;
- protected long lastRenderTime;
- /** Create a VolatileImageRenderer to render the shapes in the World w.*/
- ImageRenderer(World w, int width, int height, boolean showFPS){
- super(w, false);
- this.setOpaque(true);
- super.setSize(width, height);
- this.showFPS = showFPS;
- this.imageWidth = width;
- this.imageHeight = height;
- }
- /** Creates the image and associated Graphics object.
- */
- public abstract void init();
- /** Draw the volatile image to the screen. */
- public void paintComponent(Graphics g){
- // Let's not class the superclass version, since we are going to
- // fill the entire JPanel, anyway. No need to erase underneath.
- //super.paintComponent(g);
- if(this.backingImage == null){
- this.init();
- } else {
- // This line makes sure that when we call g.drawImage(), it will be
- // the only thread using the backingImage object.
- synchronized(this.backingImage) {
- // Only paint the backing image if it has not already
- // been painted.
- if ( ! this.wasPainted) {
- // Draw the backign image to the screen.
- g.drawImage(this.backingImage, 0 ,0, this);
- this.wasPainted = true;
- // Erase the backing image.
- clear();
- }
- // A child class render method may be waiting for this method to finish
- // via the waitUntilPainted() method, so we'll let it know that we're done.
- this.backingImage.notify();
- }
- }
- }
- /** This method is meant to be called by a child class render method, and
- * assumes that the current thread has a lock on this.backingImage. In other
- * words, it should be called inside a "synchronized" block. waitUntilPainted()
- * checks to see if the backing image has been painted to the screen yet.
- * If it has not, then the current thread is put to sleep, and will wake
- * up after the backing image has been painted. This method then terminates
- * so that execution of the child render method can continue.
- */
- protected void waitUntilPainted(){
- // If the backing image hasn't been painted to the screen yet, then
- // we'll wait until ImageRenderer.paintComponent() has finished.
- if(! this.wasPainted){
- try{
- this.backingImage.wait();
- } catch(Exception e){
- System.out.println("ImageRenderer.waitUntilPainted():"+e);
- System.exit(1);
- }
- }
- }
- /** This method is meant to be called by a child class render method, and
- * assumes that the current thread has a lock on this.backingImage. In other
- * words, it should be called inside a "synchronized" block. readyForPainting()
- * should be called at the end of the render method, just before the end
- * of the "synchronized" block. It indicates that the backing image is now
- * ready to be painted to the screen. This method calls repaint().
- */
- protected void readyForPainting(){
- // This is an optional display of fps. It generates string objects, so
- // it will trigger garbage collection eventually.
- if (this.showFPS){
- long now = System.currentTimeMillis();
- this.imageGraphics.drawString(new String("fps= " + ((int) ( 10 * (1000.0 / (now - lastRenderTime)) ) ) / 10.0 ), 10, 12);
- this.lastRenderTime = now;
- }
- // the backing image should be painted the next time
- // paintComponent() is called.
- this.wasPainted = false;
- this.repaint();
- }
- /** Erase the volatile image being used as a backing image. */
- public void clear(){
- if(this.imageGraphics != null){
- this.imageGraphics.setColor(Color.white);
- this.imageGraphics.fillRect(0, 0, this.imageWidth, this.imageHeight);
- }
- }
- /** Render triangles to the backing image. Child classes must override
- * this implementation, but should call the superclass version at the
- * beginning of their implementation.
- */
- public void render(){
- if(this.imageGraphics == null){
- this.init();
- }
- }
- /** Set the size of this JPanel and the backing image to the specified
- * dimensions.
- */
- public void setSize(int width, int height){
- super.setSize(width, height);
- this.imageWidth = width;
- this.imageHeight = height;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement