import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.font.TextLayout; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.text.DateFormat; import java.util.Date; import javax.imageio.ImageIO; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.Timer; /** * @author Donald Yessick * **/ @SuppressWarnings("serial") public class Lab8 extends JComponent { /** * main is the driver for our program * @param args not used **/ public static void main(String[] args) { Lab8 labComponent = new Lab8(); labComponent.getWindow().setVisible(true); labComponent.timer.start(); } /** * getWindow is a helper to keep main clean and simple * handles the details of creating a window * for our JComponent * @returns a window with our component **/ private JFrame getWindow() { //this is the lab8 object JFrame window = new JFrame(this.toString()); window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); window.setSize( this.getToolkit().getScreenSize()); window.setContentPane(this); return window; } /** * toString is predefined but not very usefully * @return a string representing this object **/ public String toString(){ return "lab 8"; } /** * paintComponent renders the JComponent to the window * @param Graphics **/ public void paintComponent(Graphics oldGraphics) { Graphics2D g = (Graphics2D) oldGraphics; g.setBackground(Color.ORANGE ); g.clearRect(50,50,this.getWidth()-100, this.getHeight()-100); String dateToday = DateFormat.getDateInstance(DateFormat.SHORT).format(new Date()); g.setBackground(Color.BLACK ); g.clearRect(50, this.getHeight()-150,this.getWidth()-100, 100); g.setColor(Color.ORANGE); g.setFont(new Font("Lucida Bright", Font.BOLD+Font.ITALIC, 24)); this.printCenterCaption(g, dateToday); g.transform(linearMapping); //rotation magic paintCenterURLImage(g, "http://dyessick.com/Coastal/images/don_simpson.png"); } /** * paintURLImage is a helper function that paints an image. * This method has some nastiness to it. putting it all in * paintComponent would simply make that method nasty too. * @param g Graphics2D on which to draw the image * @param stringURL universal resource locator for image */ BufferedImage simpsonize = null; private void paintCenterURLImage(Graphics2D g, String stringURL) { URL url; if (simpsonize == null){ try { url = new URL(stringURL); simpsonize = ImageIO.read(url); } catch (MalformedURLException badUrl) { badUrl.printStackTrace(); System.out.println("ABORTING: " + badUrl.toString()); System.exit(0); } catch (IOException ioError) { ioError.printStackTrace(); System.out.println("ABORTING: " + ioError.toString()); System.exit(0); } catch (Exception otherError) {//this alone is sufficient otherError.printStackTrace(); System.out.println("ABORTING: " + otherError.toString()); System.exit(0); } } int imageWidth = simpsonize.getWidth(); int imageHeight = simpsonize.getHeight(); int screenWidth = this.getWidth(); int screenHeight = this.getHeight(); int xCenter = screenWidth/2; int yCenter = screenHeight/2; int xTopLeft = xCenter - imageWidth/2; int yTopLeft = yCenter - imageHeight/2; int xBottomRight = xTopLeft+imageWidth; int yBottomRight = yTopLeft+imageHeight; g.drawImage( //scales and draws image on the fly simpsonize, //the image xTopLeft, yTopLeft, //top left coordinate to place image xBottomRight,yBottomRight, //bottom right coordinate to scale image 0, 0, //where to start in the image --you can choose part of the image imageWidth,imageHeight, //where to end in the image --you can choose part of the image null, //transparent fill color, e.g. Color.YELLOW, leave as null, or omit to leave transparent null); //ImageObserver -- null will do -- can be used to alert when finished } /** * centerString draws a string centered at the bottom of the window * @param g Graphics2D on which to draw the text * @param text String to draw */ private void printCenterCaption(Graphics2D g, String text) { TextLayout graphicRep; graphicRep = new TextLayout(text, g.getFont(), g.getFontRenderContext()); int winWidth = this.getWidth(); int winHeight = this.getHeight()-50 ;//50 is my bottom border int txtWidth = graphicRep.getBounds().getBounds().width; //I know, I know, "getBounds().getBounds()" it is ridiculous int txtHeight = graphicRep.getBounds().getBounds().height;//but other methods were no less clean (the first getBounds is type double) graphicRep.draw(g, winWidth/2-txtWidth/2, (winHeight)-(100-txtHeight)/2); //the space is 100 high } /** * The AffineTransform class represents a 2D affine transform that performs a linear mapping from 2D coordinates to other 2D coordinates * that preserves the "straightness" and "parallelness" of lines. Affine transformations can be constructed using sequences of * translations, scales, flips, rotations, and shears. * * Such a coordinate transformation can be represented by a 3 row by 3 column matrix with an implied last row of [ 0 0 1 ]. * This matrix transforms source coordinates (x,y) into destination coordinates (x',y') by considering them to be a column vector * and multiplying the coordinate vector by the matrix according to the following process: [ x'] [ m00 m01 m02 ] [ x ] [ m00x + m01y + m02 ] [ y'] = [ m10 m11 m12 ] [ y ] = [ m10x + m11y + m12 ] [ 1 ] [ 0 0 1 ] [ 1 ] [ 1 */ private AffineTransform linearMapping = new AffineTransform();//will store the rotation transform /** * timer forces repainting (with new rotation) every 15000 milliseconds (15 seconds)) * this is syntactically ugly so don't get hung up on it * key idea, repaint(), forces the screen to repaint */ protected Timer timer = new Timer(500, new ActionListener(){ public void actionPerformed(ActionEvent time){ linearMapping.rotate(Math.PI/180*3.14, getWidth()/2, getHeight()/2); //rotates linearMapping 3.14 degrees (in radians) repaint(); }}); }