Java tutorial
import java.awt.Color; import java.awt.Graphics; import java.awt.Rectangle; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.SwingUtilities; /* * CopyAreaPerformance.java * * Created on May 1, 2007, 4:24 PM * * Copyright (c) 2007, Sun Microsystems, Inc * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the TimingFramework project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * * @author Chet */ public class CopyAreaPerformance extends JComponent implements KeyListener { private static final int SMILEY_SIZE = 10; private static final int PADDING = 2; private static final int MIN_COLOR = 0; private static final int CANVAS_W = SMILEY_SIZE * (256 - MIN_COLOR); private static final int CANVAS_H = SMILEY_SIZE * (256 - MIN_COLOR); private static final int SCROLL_SIZE = 100; private int viewX = CANVAS_W / 2; private int viewY = CANVAS_H / 2; private boolean useCopyArea = false; private boolean useClip = false; int prevVX; int prevVY; /** Creates a new instance of CopyAreaPerformance */ public CopyAreaPerformance() { setOpaque(true); } private void drawSmiley(Graphics g, Color faceColor, int x, int y) { // fill face color g.setColor(faceColor); g.fillOval(x, y, SMILEY_SIZE, SMILEY_SIZE); g.setColor(Color.BLACK); // draw head g.drawOval(x, y, SMILEY_SIZE, SMILEY_SIZE); // draw smile g.drawArc(x + (int) ((SMILEY_SIZE * .2)), (int) (y + (SMILEY_SIZE * .2)), (int) (SMILEY_SIZE * .6), (int) (SMILEY_SIZE * .6), 200, 140); // draw eyes int eyeSize = Math.max(2, (int) (SMILEY_SIZE * .1)); g.fillOval(x + (int) ((SMILEY_SIZE * .5) - (SMILEY_SIZE * .1) - eyeSize), y + (int) (SMILEY_SIZE * .3), eyeSize, eyeSize); g.fillOval(x + (int) ((SMILEY_SIZE * .5) + (SMILEY_SIZE * .1)), y + (int) (SMILEY_SIZE * .3), eyeSize, eyeSize); } protected void paintComponent(Graphics g) { long startTime = System.nanoTime(); // prevVX is set to -10000 when first enabled if (useCopyArea && prevVX > -9999) { // Most of this code determines the proper areas to copy and clip int scrollX = viewX - prevVX; int scrollY = viewY - prevVY; int copyFromY, copyFromX; int clipFromY, clipFromX; if (scrollX == 0) { // vertical scroll if (scrollY < 0) { copyFromY = 0; clipFromY = 0; } else { copyFromY = scrollY; clipFromY = getHeight() - scrollY; } // copy the old content, set the clip to the new area g.copyArea(0, copyFromY, getWidth(), getHeight() - Math.abs(scrollY), 0, -scrollY); g.setClip(0, clipFromY, getWidth(), Math.abs(scrollY)); } else { // horizontal scroll if (scrollX < 0) { copyFromX = 0; clipFromX = 0; } else { copyFromX = scrollX; clipFromX = getWidth() - scrollX; } // copy the old content, set the clip to the new area g.copyArea(copyFromX, 0, getWidth() - Math.abs(scrollX), getHeight(), -scrollX, 0); g.setClip(clipFromX, 0, Math.abs(scrollX), getHeight()); } } // Track previous view position for next scrolling operation prevVX = viewX; prevVY = viewY; // Get the clip in case we need it later Rectangle clipRect = g.getClip().getBounds(); int clipL = (int) (clipRect.getX()); int clipT = (int) (clipRect.getY()); int clipR = (int) (clipRect.getMaxX()); int clipB = (int) (clipRect.getMaxY()); g.setColor(Color.WHITE); g.fillRect(clipL, clipT, (int) clipRect.getWidth(), (int) clipRect.getHeight()); for (int column = 0; column < 256; ++column) { int x = column * (SMILEY_SIZE + PADDING) - viewX; if (useClip) { if (x > clipR || (x + (SMILEY_SIZE + PADDING)) < clipL) { // trivial reject; outside to the left or right continue; } } for (int row = 0; row < 256; ++row) { int y = row * (SMILEY_SIZE + PADDING) - viewY; if (useClip) { if (y > clipB || (y + (SMILEY_SIZE + PADDING)) < clipT) { // trivial reject; outside to the top or bottom continue; } } Color faceColor = new Color(column, row, 0); drawSmiley(g, faceColor, x, y); } } long stopTime = System.nanoTime(); System.out.println("Painted in " + ((stopTime - startTime) / 1000000) + " ms"); } private void scroll(int scrollX, int scrollY) { viewX += scrollX; viewY += scrollY; viewX = Math.max(viewX, 0); viewX = Math.min(viewX, CANVAS_W - viewX); viewY = Math.max(viewY, 0); viewY = Math.min(viewY, CANVAS_H - viewY); repaint(); } // KeyListener methods /** * Arrow keys scroll the view around. The 'c' key toggles clip area * optimization. The 'a' key toggles copyArea optimization. */ public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_RIGHT) { scroll(SCROLL_SIZE, 0); } else if (e.getKeyCode() == KeyEvent.VK_LEFT) { scroll(-SCROLL_SIZE, 0); } else if (e.getKeyCode() == KeyEvent.VK_UP) { scroll(0, -SCROLL_SIZE); } else if (e.getKeyCode() == KeyEvent.VK_DOWN) { scroll(0, SCROLL_SIZE); } else if (e.getKeyCode() == KeyEvent.VK_C) { useClip = !useClip; System.out.println("useClip = " + useClip); } else if (e.getKeyCode() == KeyEvent.VK_A) { useCopyArea = !useCopyArea; prevVX = -10000; System.out.println("useCopyArea = " + useCopyArea); } } public void keyReleased(KeyEvent e) { } public void keyTyped(KeyEvent e) { } private static void createAndShowGUI() { JFrame f = new JFrame("CopyAreaPerformance"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setSize(600, 600); CopyAreaPerformance component = new CopyAreaPerformance(); f.add(component); f.addKeyListener(component); f.setVisible(true); } public static void main(String args[]) { Runnable doCreateAndShowGUI = new Runnable() { public void run() { createAndShowGUI(); } }; SwingUtilities.invokeLater(doCreateAndShowGUI); } }