import java.awt.*; // import statements to make necessary classes available import java.awt.geom.*; import javax.swing.*; /** * This class shows the setup for drawing static images using Java Graphics2D. * The drawing code goes in the paintComponent() method. When the program * is run, the drawing is shown in a window on the screen. See AnimationStarter.java * for a somewhat more useful framework. */ public class GraphicsStarter extends JPanel { /** * This main() routine makes it possible to run the class GraphicsStarter * as an application. It simply creates a window that contains a panel * of type GraphicsStarter. The program ends when the user closed the * window by clicking its close box. */ public static void main(String[] args) { JFrame window; window = new JFrame("Java Graphics"); // The parameter shows in the window title bar. window.setContentPane( new GraphicsStarter() ); // Show a Graphics starter in the window. window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // End program when window closes. window.pack(); // Set window size based on the preferred sizes of its contents. window.setResizable(false); // Don't let user resize window. Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); window.setLocation( // Center window on screen. (screen.width - window.getWidth())/2, (screen.height - window.getHeight())/2 ); window.setVisible(true); // Open the window, making it visible on the screen. } private float pixelSize; // This is the measure of a pixel in the coordinate system // set up by calling the applyLimits method. It can be used // for setting line widths, for example. /** * This constructor sets up a GraphicsStarter when it is created. Here, it * sets the size of the drawing area. (The size is set as a "preferred size," * which will be used by the pack() command in the main() routine.) */ public GraphicsStarter() { setPreferredSize( new Dimension(800,600) ); // Set size of drawing area, in pixels. } /** * The paintComponent method draws the content of the JPanel. The parameter * is a graphics context that can be used for drawing on the panel. Note that * it is declared to be of type Graphics but is actually of type Graphics2D, * which is a subclass of Graphics. */ protected void paintComponent(Graphics g) { /* First, create a Graphics2D drawing context for drawing on the panel. * (g.create() makes a copy of g, which will draw to the same place as g, * but changes to the returned copy will not affect the original.) */ Graphics2D g2 = (Graphics2D)g.create(); /* Turn on antialiasing in this graphics context, for better drawing. */ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); /* Fill in the entire drawing area with white. */ g2.setPaint(Color.WHITE); g2.fillRect(0,0,getWidth(),getHeight()); // From the old graphics API! /* Here, I set up a new coordinate system on the drawing area, by calling * the applyLimits() method that is defined below. Without this call, I * would be using regular pixel coordinates. This function sets the global * variable pixelSize, which I need for stroke widths in the transformed * coordinate system. */ applyapplyWindowToViewportTransformation(g2, -5, 5, -5, 5, true); /* Finish by drawing a few shapes as an example. You can erase the rest of * this subroutine and substitute your own drawing. */ g2.setPaint(Color.YELLOW); g2.fill( new Ellipse2D.Double(-6,-1,12,2) ); g2.setPaint(Color.BLUE); g2.setStroke( new BasicStroke(5*pixelSize) ); g2.draw( new Line2D.Double( -5, -5, 5, 5) ); g2.draw( new Line2D.Double( -5, 5, 5, -5) ); Path2D poly = new Path2D.Double(); poly.moveTo(3,0); for (int i = 1; i < 6; i++) { double angle = (2*Math.PI/6) * i; poly.lineTo( 3*Math.cos(angle), 3*Math.sin(angle) ); } poly.closePath(); g2.setPaint( new Color(255, 0, 0, 100) ); // red with alpha-transparency g2.fill(poly); g2.setPaint( Color.RED ); g2.draw(poly); } /** * Applies a coordinate transform to a Graphics2D graphics context. The upper * left corner of the viewport where the graphics context draws is assumed to * be (0,0). The coordinate transform will make a requested view window visible * in the drawing area. The requested limits might be adjusted to preserve the * aspect ratio. * This method sets the value of the global variable pixelSize, which is defined as the * maximum of the width of a pixel and the height of a pixel as measured in the * coordinate system. (If the aspect ratio is preserved, then the width and * height will agree. * @param g2 The drawing context whose transform will be set. * @param left requested x-value at left of drawing area. * @param right requested x-value at right of drawing area. * @param bottom requested y-value at bottom of drawing area; can be less than * top, which will reverse the orientation of the y-axis to make the positive * direction point upwards. * @param top requested y-value at top of drawing area. * @param preserveAspect if preserveAspect is false, then the requested view window * rectangle will exactly fill the viewport; if it is true, then the limits will be * expanded in one direction, horizontally or vertically, if necessary, to make the * aspect ratio of the view window match the aspect ratio of the viewport. * Note that when preserveAspect is false, the units of measure in the horizontal * and vertical directions will be different. */ private void applyapplyWindowToViewportTransformation(Graphics2D g2, double left, double right, double bottom, double top, boolean preserveAspect) { int width = getWidth(); // The width of this drawing area, in pixels. int height = getHeight(); // The height of this drawing area, in pixels. if (preserveAspect) { // Adjust the limits to match the aspect ratio of the drawing area. double displayAspect = Math.abs((double)height / width); double requestedAspect = Math.abs(( bottom-top ) / ( right-left )); if (displayAspect > requestedAspect) { // Expand the viewport vertically. double excess = (bottom-top) * (displayAspect/requestedAspect - 1); bottom += excess/2; top -= excess/2; } else if (displayAspect < requestedAspect) { // Expand the viewport vertically. double excess = (right-left) * (requestedAspect/displayAspect - 1); right += excess/2; left -= excess/2; } } g2.scale( width / (right-left), height / (bottom-top) ); g2.translate( -left, -top ); double pixelWidth = Math.abs(( right - left ) / width); double pixelHeight = Math.abs(( bottom - top ) / height); pixelSize = (float)Math.max(pixelWidth,pixelHeight); } }