【问题标题】:How to use custom axis type? (Java)如何使用自定义轴类型? (爪哇)
【发布时间】:2015-03-24 15:10:19
【问题描述】:

我想开发一个桌面应用程序,它能够绘制给定函数的图形,但在具有自定义轴的坐标系中。 例如:用户可以在 X 轴和 Y 轴的情况下在线性、对数、指数等轴类型之间进行切换。

  • 您认为Java AWT 适合此目的吗? (我还不知道),
  • 您知道可以/应该使用哪些其他技术吗?
  • 在这种情况下时间是最重要的,所以我需要最简单的方法..

提前谢谢你, 马顿

【问题讨论】:

    标签: java function graph awt axis


    【解决方案1】:

    Swing 或 JavaFX 会比 AWT 更好。

    这是我开发的一些代码,用于在 Swing 绘图区域上放置笛卡尔和/或极坐标系。您可以以此为起点来做您想做的事。

    坐标系类

    package com.ggl.game.utilities;
    
    import java.awt.Dimension;
    import java.awt.Point;
    import java.awt.geom.Point2D;
    
    /**
     * <p>
     * This class creates a Cartesian and Polar coordinate system to overlay a Swing
     * drawing area (usually a <code>JPanel</code>). The user of the class sets a
     * limit as to how far the X axis or the Y axis extends in the negative and
     * positive direction from (0, 0). Point (0, 0) will be placed in the center of
     * the drawing area.
     * </p>
     * <p>
     * Since the drawing area is usually not square, the limit applies to the
     * shorter dimension. The actual limits can be retrieved from this class, and
     * will change if the user of the application changes the drawing area size by
     * maximizing or normalizing the application <code>JFrame</code> window.
     * </p>
     * <p>
     * Using a Cartesian or Polar coordinate system frees the user of this class
     * from having to worry about Swing pixel coordinates.
     * </p>
     * 
     * @author Gilbert G. Le Blanc
     * @version 1.0 - 23 February 2015
     * 
     * @see com.ggl.game.utilities.Polar2D
     * @see java.awt.geom.Point2D
     * @see javax.swing.JFrame
     * @see javax.swing.JPanel
     */
    public class CoordinateSystem {
    
        private double conversionFactor;
        private double xLimit;
        private double yLimit;
    
        private int height;
        private int width;
    
        /**
         * <p>
         * This creates a Cartesian and Polar coordinate system over a Swing drawing
         * area (usually a <code>JPanel</code>). If the drawing area is square, the
         * X axis extends from -limit to limit and the Y axis extends from -limit to
         * limit.
         * </p>
         * <p>
         * If the drawing area is not square, then the smaller dimension, either X
         * or Y, extends from -limit to limit. The larger dimension extends beyond
         * the limit in both directions.
         * </p>
         * <p>
         * Since most displays are not square, the X and Y axis will usually have
         * different limits.
         * </p>
         * 
         * @param limit
         *            - The limit of the X and Y axis in a Cartesian coordinate
         *            system.
         * @param width
         *            - The width of the drawing area in pixels.
         * @param height
         *            - The height of the drawing area in pixels.
         */
        public CoordinateSystem(double limit, int width, int height) {
            this.width = width;
            this.height = height;
    
            if (width > height) {
                this.xLimit = limit * width / height;
                this.yLimit = limit;
                this.conversionFactor = (limit + limit) / (double) height;
            } else if (width < height) {
                this.xLimit = limit;
                this.yLimit = limit * height / width;
                this.conversionFactor = (limit + limit) / (double) width;
            } else {
                this.xLimit = limit;
                this.yLimit = limit;
                this.conversionFactor = (limit + limit) / (double) width;
            }
        }
    
        /**
         * This method changes the drawing area dimension, along with the X and Y
         * axis limits.
         * 
         * @param dimension
         *            - A <code>Dimension</code> with the new drawing area
         *            dimension.
         */
        public void setDrawingSize(Dimension dimension) {
            setDrawingSize(dimension.width, dimension.height);
        }
    
        /**
         * This method changes the drawing area width and height, along with the X
         * and Y axis limits.
         * 
         * @param width
         *            - The width of the drawing area in pixels.
         * @param height
         *            - The height of the drawing area in pixels.
         */
        public void setDrawingSize(int width, int height) {
            xLimit = xLimit / this.width * width;
            yLimit = yLimit / this.height * height;
    
            this.width = width;
            this.height = height;
        }
    
        /**
         * This method returns the Cartesian coordinate limit for the X axis.
         * 
         * @return The Cartesian coordinate limit for the X axis.
         */
        public double getxLimit() {
            return xLimit;
        }
    
        /**
         * This method returns the Cartesian coordinate limit for the Y axis.
         * 
         * @return The Cartesian coordinate limit for the Y axis.
         */
        public double getyLimit() {
            return yLimit;
        }
    
        /**
         * This method converts a Polar coordinate distance and theta angle in
         * radians to a pixel location on a drawing area.
         * 
         * @param distance
         *            - A Polar coordinate distance
         * @param theta
         *            - A Polar coordinate theta angle in radians
         * @return A pixel location on a drawing area.
         */
        public Point convertPolarToPixels(double distance, double theta) {
            return convertToPixels(new Polar2D.Double(distance, theta));
        }
    
        /**
         * This method converts a Cartesian coordinate x and y to a pixel location
         * on a drawing area.
         * 
         * @param x
         *            - A Cartesian coordinate x.
         * @param y
         *            - A Cartesian coordinate y.
         * @return A pixel location on a drawing area.
         */
        public Point convertPointToPixels(double x, double y) {
            return convertToPixels(new Point2D.Double(x, y));
        }
    
        /**
         * This method converts a Polar coordinate to a pixel location on a drawing
         * area.
         * 
         * @param polar
         *            - A Polar coordinate.
         * @return A pixel location on a drawing area.
         */
        public Point convertToPixels(Polar2D polar) {
            double x = polar.getDistance() * Math.cos(polar.getTheta());
            double y = polar.getDistance() * Math.sin(polar.getTheta());
            return convertToPixels(new Point2D.Double(x, y));
        }
    
        /**
         * This method converts a Cartesian coordinate to a pixel location on a
         * drawing area.
         * 
         * @param cartesian
         *            - A Cartesian coordinate.
         * @return A pixel location on a drawing area.
         */
        public Point convertToPixels(Point2D cartesian) {
            int x = (int) Math
                    .round((cartesian.getX() + xLimit) / conversionFactor);
            int y = (int) Math.round((-cartesian.getY() + yLimit)
                    / conversionFactor);
            return new Point(x, y);
        }
    
        /**
         * This method converts a pixel location on a drawing area to a Cartesian
         * coordinate.
         * 
         * @param x
         *            - The x pixel location.
         * @param y
         *            - The y pixel location.
         * @return A Cartesian coordinate.
         */
        public Point2D convertToCartesian(int x, int y) {
            return convertToCartesian(new Point(x, y));
        }
    
        /**
         * This method converts a pixel location on a drawing area to a Cartesian
         * coordinate.
         * 
         * @param point
         *            - The pixel location.
         * @return A Cartesian coordinate.
         */
        public Point2D convertToCartesian(Point point) {
            double x = (double) point.x * conversionFactor - xLimit;
            double y = (double) -point.y * conversionFactor + yLimit;
            return new Point2D.Double(x, y);
        }
    
        /**
         * This method converts a pixel location on a drawing area to a Polar
         * coordinate.
         * 
         * @param x
         *            - The x pixel location.
         * @param y
         *            - The y pixel location.
         * @return A Polar coordinate.
         */
        public Polar2D convertToPolar(int x, int y) {
            return convertToPolar(new Point(x, y));
        }
    
        /**
         * This method converts a pixel location on a drawing area to a Polar
         * coordinate.
         * 
         * @param point
         *            - The pixel location.
         * @return A Polar coordinate.
         */
        public Polar2D convertToPolar(Point point) {
            double x = (double) point.x * conversionFactor - xLimit;
            double y = (double) -point.y * conversionFactor + yLimit;
            double distance = Math.sqrt(x * x + y * y);
            double theta = Math.atan2(y, x);
            return new Polar2D.Double(distance, theta);
        }
    
    }
    

    Polar2D 类

    package com.ggl.game.utilities;
    
    /**
     * The <code>Polar2D</code> class defines a point representing a location in
     * distance, theta angle coordinate space.
     * <p>
     * This class is only the abstract superclass for all objects that store a 2D
     * coordinate. The actual storage representation of the coordinates is left to
     * the subclass.
     * 
     * @version 1.0 - 23 February 2015
     * @author Jim Graham (author of Point2D), Gilbert Le Blanc
     */
    public abstract class Polar2D implements Cloneable {
        /**
         * The <code>Float</code> class defines a point specified in float
         * precision.
         */
        public static class Float extends Polar2D {
            /**
             * The distance of this <code>Polar2D</code>.
             * 
             * @since 1.7
             */
            public float distance;
            /**
             * The theta angle of this <code>Polar2D</code>.
             * 
             * @since 1.7
             */
            public float theta;
    
            /**
             * Constructs and initializes a <code>Polar2D</code> with coordinates
             * (0,&nbsp;0).
             * 
             * @since 1.7
             */
            public Float() {
            }
    
            /**
             * Constructs and initializes a <code>Polar2D</code> with the specified
             * coordinates.
             * 
             * @param distance
             *            The distance to which to set the newly constructed
             *            <code>Polar2D</code>
             * @param theta
             *            The theta angle in radians to which to set the newly
             *            constructed <code>Polar2D</code>
             * @since 1.7
             */
            public Float(float distance, float theta) {
                this.distance = distance;
                this.theta = theta;
            }
    
            /**
             * Returns the distance of this <code>Polar2D</code> in
             * <code>double</code> precision.
             * 
             * @return the distance of this <code>Polar2D</code>.
             * @since 1.7
             */
            @Override
            public double getDistance() {
                return (double) distance;
            }
    
            /**
             * Returns the theta angle in radians of this <code>Polar2D</code> in
             * <code>double</code> precision.
             * 
             * @return the theta angle in radians of this <code>Polar2D</code>.
             * @since 1.7
             */
            @Override
            public double getTheta() {
                return (double) theta;
            }
    
            /**
             * Returns the theta angle in degrees of this <code>Polar2D</code> in
             * <code>double</code> precision.
             * 
             * @return the theta angle in degrees of this <code>Polar2D</code>.
             * @since 1.7
             */
            @Override
            public double getThetaInDegrees() {
                double degrees = 180D / Math.PI * theta;
                return (degrees < 0D) ? degrees + 360D : degrees;
            }
    
            /**
             * Sets the location of this <code>Polar2D</code> to the specified
             * <code>double</code> distance and theta angle in radians.
             * 
             * @param distance
             *            The distance to which to set this <code>Polar2D</code>
             * @param theta
             *            The theta angle in radians to which to set this
             *            <code>Polar2D</code>
             * @since 1.7
             */
            @Override
            public void setLocation(double distance, double theta) {
                this.distance = (float) distance;
                this.theta = (float) theta;
            }
    
            /**
             * Sets the location of this <code>Polar2D</code> to the specified
             * <code>float</code> coordinates.
             * 
             * @param distance
             *            The distance to which to set this <code>Polar2D</code>
             * @param theta
             *            The theta angle in radians to which to set this
             *            <code>Polar2D</code>
             * @since 1.7
             */
            public void setLocation(float distance, float theta) {
                this.distance = distance;
                this.theta = theta;
            }
    
            /**
             * Returns a <code>String</code> that represents the value of this
             * <code>Polar2D</code>.
             * 
             * @return A <code>String</code> representation of this
             *         <code>Polar2D</code>.
             * @since 1.7
             */
            @Override
            public String toString() {
                return "Polar2D.Float[" + distance + ", " + theta + "]";
            }
        }
    
        /**
         * The <code>Double</code> class defines a point specified in
         * <code>double</code> precision.
         */
        public static class Double extends Polar2D {
            /**
             * The distance of this <code>Polar2D</code>.
             * 
             * @since 1.7
             */
            public double distance;
            /**
             * The theta angle in radians of this <code>Polar2D</code>.
             * 
             * @since 1.7
             */
            public double theta;
    
            /**
             * Constructs and initializes a <code>Polar2D</code> with (0,&nbsp;0)
             * distance and theta angle in radians.
             * 
             * @since 1.7
             */
            public Double() {
            }
    
            /**
             * Constructs and initializes a <code>Polar2D</code> with the specified
             * coordinates.
             * 
             * @param distance
             *            The distance to which to set the newly constructed
             *            <code>Polar2D</code>
             * @param theta
             *            The theta angle in radians to which to set the newly
             *            constructed <code>Polar2D</code>
             * @since 1.7
             */
            public Double(double distance, double theta) {
                this.distance = distance;
                this.theta = theta;
            }
    
            /**
             * Returns the distance of this <code>Polar2D</code> in
             * <code>double</code> precision.
             * 
             * @return The distance of this <code>Polar2D</code>.
             * @since 1.7
             */
            @Override
            public double getDistance() {
                return distance;
            }
    
            /**
             * Returns the theta angle in radians of this <code>Polar2D</code> in
             * <code>double</code> precision.
             * 
             * @return The theta angle in radians of this <code>Polar2D</code>.
             * @since 1.7
             */
            @Override
            public double getTheta() {
                return theta;
            }
    
            /**
             * Returns the theta angle in degrees of this <code>Polar2D</code> in
             * <code>double</code> precision.
             * 
             * @return The theta angle in degrees of this <code>Polar2D</code>.
             * @since 1.7
             */
            @Override
            public double getThetaInDegrees() {
                double degrees = 180D / Math.PI * theta;
                return (degrees < 0D) ? degrees + 360D : degrees;
            }
    
            /**
             * Sets the location of this <code>Polar2D</code> to the specified
             * <code>double</code> coordinates.
             * 
             * @param distance
             *            The distance to which to set this <code>Polar2D</code>
             * @param theta
             *            The theta angle in radians to which to set this
             *            <code>Polar2D</code>
             * @since 1.7
             */
            @Override
            public void setLocation(double distance, double theta) {
                this.distance = distance;
                this.theta = theta;
            }
    
            /**
             * Returns a <code>String</code> that represents the value of this
             * <code>Polar2D</code>.
             * 
             * @return A <code>String</code> representation of this
             *         <code>Polar2D</code>.
             * @since 1.7
             */
            @Override
            public String toString() {
                return "Polar2D.Double[" + distance + ", " + theta + "]";
            }
        }
    
        /**
         * This is an abstract class that cannot be instantiated directly.
         * Type-specific implementation subclasses are available for instantiation
         * and provide a number of formats for storing the information necessary to
         * satisfy the various accessor methods below.
         * 
         * @see java.awt.geom.Polar2D.Float
         * @see java.awt.geom.Polar2D.Double
         * @see java.awt.Point
         */
        protected Polar2D() {
        }
    
        /**
         * Returns the distance of this <code>Polar2D</code> in <code>double</code>
         * precision.
         * 
         * @return The distance of this <code>Polar2D</code>.
         * @since 1.7
         */
        public abstract double getDistance();
    
        /**
         * Returns the theta angle in radians of this <code>Polar2D</code> in
         * <code>double</code> precision.
         * 
         * @return The theta angle in radians of this <code>Polar2D</code>.
         * @since 1.7
         */
        public abstract double getTheta();
    
        /**
         * Returns the theta angle in degrees of this <code>Polar2D</code> in
         * <code>double</code> precision.
         * 
         * @return The theta angle in degrees of this <code>Polar2D</code>.
         * @since 1.7
         */
        public abstract double getThetaInDegrees();
    
        /**
         * Sets the location of this <code>Polar2D</code> to the specified
         * <code>double</code> coordinates.
         * 
         * @param distance
         *            The distance of this <code>Polar2D</code>
         * @param theta
         *            The theta angle in radians of this <code>Polar2D</code>
         * @since 1.7
         */
        public abstract void setLocation(double distance, double theta);
    
        /**
         * Sets the location of this <code>Polar2D</code> to the same coordinates as
         * the specified <code>Polar2D</code> object.
         * 
         * @param p
         *            the specified <code>Polar2D</code> the which to set this
         *            <code>Polar2D</code>
         * @since 1.7
         */
        public void setLocation(Polar2D p) {
            setLocation(p.getDistance(), p.getTheta());
        }
    
        /**
         * Returns the square of the distance between two points.
         * 
         * @param distance1
         *            The distance of the first point
         * @Parm theta1 The theta angle in radians of the first point
         * @param distance2
         *            The distance of the second point
         * @param theta2
         *            The theta angle in radians of the second point
         * @return The square of the distance between the two specified points.
         */
        public static double distanceSq(double distance1, double theta1,
                double distance2, double theta2) {
            double x1 = distance1 * Math.cos(theta1);
            double y1 = distance1 * Math.sin(theta1);
            double x2 = distance2 * Math.cos(theta2);
            double y2 = distance2 * Math.sin(theta2);
            return (x1 * x2 + y1 * y2);
        }
    
        /**
         * Returns the distance between two points.
         * 
         * @param distance1
         *            The distance of the first point
         * @param theta1
         *            The theta angle in radians of the first point
         * @param distance2
         *            The distance of the second point
         * @param theta2
         *            The theta angle in radians of the second point
         * @return The distance between the two specified points.
         */
        public static double distance(double distance1, double theta1,
                double distance2, double theta2) {
            double x1 = distance1 * Math.cos(theta1);
            double y1 = distance1 * Math.sin(theta1);
            double x2 = distance2 * Math.cos(theta2);
            double y2 = distance2 * Math.sin(theta2);
            return Math.sqrt(x1 * x2 + y1 * y2);
        }
    
        /**
         * Returns the square of the distance from this <code>Polar2D</code> to a
         * specified point.
         * 
         * @param distance
         *            The distance of the specified point
         * @param theta
         *            The theta angle in radians of the specified point
         * @return The square of the distance between this <code>Polar2D</code> and
         *         the specified point.
         */
        public double distanceSq(double distance, double theta) {
            double x1 = distance * Math.cos(theta);
            double y1 = distance * Math.sin(theta);
            double x2 = getDistance() * Math.cos(getTheta());
            double y2 = getDistance() * Math.sin(getTheta());
            return (x1 * x2 + y1 * y2);
        }
    
        /**
         * Returns the square of the distance from this <code>Polar2D</code> to a
         * specified <code>Polar2D</code>.
         * 
         * @param pt
         *            The specified <code>Polar2D</code>
         * @return The square of the distance between this <code>Polar2D</code> to a
         *         specified <code>Polar2D</code>.
         */
        public double distanceSq(Polar2D pt) {
            double x1 = pt.getDistance() * Math.cos(pt.getTheta());
            double y1 = pt.getDistance() * Math.sin(pt.getTheta());
            double x2 = getDistance() * Math.cos(getTheta());
            double y2 = getDistance() * Math.sin(getTheta());
            return (x1 * x2 + y1 * y2);
        }
    
        /**
         * Returns the distance from this <code>Polar2D</code> to a specified point.
         * 
         * @param distance
         *            The distance of the specified point
         * @param theta
         *            The theta angle in radians of the specified point
         * @return The distance between this <code>Polar2D</code> and a specified
         *         point.
         */
        public double distance(double distance, double theta) {
            double x1 = distance * Math.cos(theta);
            double y1 = distance * Math.sin(theta);
            double x2 = getDistance() * Math.cos(getTheta());
            double y2 = getDistance() * Math.sin(getTheta());
            return Math.sqrt(x1 * x2 + y1 * y2);
        }
    
        /**
         * Returns the distance from this <code>Polar2D</code> to a specified
         * <code>Polar2D</code>.
         * 
         * @param pt
         *            the specified <code>Polar2D</code>
         * @return The distance between this <code>Polar2D</code> and the specified
         *         <code>Polar2D</code>.
         */
        public double distance(Polar2D pt) {
            double x1 = pt.getDistance() * Math.cos(pt.getTheta());
            double y1 = pt.getDistance() * Math.sin(pt.getTheta());
            double x2 = getDistance() * Math.cos(getTheta());
            double y2 = getDistance() * Math.sin(getTheta());
            return Math.sqrt(x1 * x2 + y1 * y2);
        }
    
        /**
         * Creates a new object of the same class and with the same contents as this
         * object.
         * 
         * @return a clone of this instance.
         * @exception OutOfMemoryError
         *                if there is not enough memory.
         * @see java.lang.Cloneable
         * @since 1.7
         */
        @Override
        public Object clone() {
            try {
                return super.clone();
            } catch (CloneNotSupportedException e) {
                // this shouldn't happen, since we are Cloneable
                throw new InternalError();
            }
        }
    
        /**
         * Returns the hash code for this <code>Polar2D</code>.
         * 
         * @return a hash code for this <code>Polar2D</code>.
         */
        @Override
        public int hashCode() {
            long bits = java.lang.Double.doubleToLongBits(getDistance());
            bits ^= java.lang.Double.doubleToLongBits(getTheta()) * 31;
            return (((int) bits) ^ ((int) (bits >> 32)));
        }
    
        /**
         * Determines whether or not two points are equal. Two instances of
         * <code>Polar2D</code> are equal if the values of their <code>x</code> and
         * <code>y</code> member fields, representing their position in the
         * coordinate space, are the same.
         * 
         * @param obj
         *            an object to be compared with this <code>Polar2D</code>
         * @return <code>true</code> if the object to be compared is an instance of
         *         <code>Polar2D</code> and has the same values; <code>false</code>
         *         otherwise.
         * @since 1.7
         */
        @Override
        public boolean equals(Object obj) {
            if (obj instanceof Polar2D) {
                Polar2D p2d = (Polar2D) obj;
                return (getDistance() == p2d.getDistance())
                        && (getTheta() == p2d.getTheta());
            }
            return super.equals(obj);
        }
    }
    

    在另一个答案中继续。

    【讨论】:

      【解决方案2】:

      从答案的第一部分继续,因为答案有 30,000 个字符的限制。

      这里有一些代码来测试答案第一部分中的两个类。

      CoordinateSystemTester 类

      package com.ggl.game.utilities.swing;
      
      import java.awt.BasicStroke;
      import java.awt.BorderLayout;
      import java.awt.Color;
      import java.awt.Dimension;
      import java.awt.Font;
      import java.awt.Graphics;
      import java.awt.Graphics2D;
      import java.awt.Point;
      import java.awt.Rectangle;
      import java.awt.event.ComponentAdapter;
      import java.awt.event.ComponentEvent;
      import java.awt.event.MouseAdapter;
      import java.awt.event.MouseEvent;
      import java.awt.font.FontRenderContext;
      import java.awt.geom.Point2D;
      import java.awt.geom.Rectangle2D;
      
      import javax.swing.JFrame;
      import javax.swing.JPanel;
      import javax.swing.SwingUtilities;
      
      import com.ggl.game.utilities.CoordinateSystem;
      import com.ggl.game.utilities.Polar2D;
      
      public class CoordinateSystemTester implements Runnable {
      
          private DrawingPanel drawingPanel;
      
          private JFrame frame;
      
          @Override
          public void run() {
              frame = new JFrame("Coordinate System Tester");
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      
              JPanel mainPanel = new JPanel();
              mainPanel.setLayout(new BorderLayout());
      
              drawingPanel = new DrawingPanel(640, 480);
              mainPanel.add(drawingPanel);
      
              frame.add(mainPanel);
      
              frame.pack();
              frame.setLocationByPlatform(true);
              frame.setVisible(true);
          }
      
          public static void main(String[] args) {
              SwingUtilities.invokeLater(new CoordinateSystemTester());
          }
      
          private class DrawingPanel extends JPanel {
      
              private static final long serialVersionUID = 1519119839534910933L;
      
              private CoordinateSystem coordinateSystem;
      
              private Point pixelPoint;
      
              private Point2D coordinatePoint;
      
              private String coordinateString;
      
              public DrawingPanel(int width, int height) {
                  this.coordinateSystem = new CoordinateSystem(25.0D, width, height);
                  this.coordinatePoint = new Point2D.Double();
                  this.pixelPoint = new Point();
                  this.coordinateString = "";
      
                  addComponentListener(new SizeListener());
                  addMouseListener(new CoordinateListener());
                  setPreferredSize(new Dimension(width, height));
              }
      
              public CoordinateSystem getCoordinateSystem() {
                  return coordinateSystem;
              }
      
              public Point2D getCoordinatePoint() {
                  return coordinatePoint;
              }
      
              public void setCoordinatePoint(Point2D coordinatePoint) {
                  this.coordinatePoint = coordinatePoint;
              }
      
              public Point getPixelPoint() {
                  return pixelPoint;
              }
      
              public void setPixelPoint(Point pixelPoint) {
                  this.pixelPoint = pixelPoint;
              }
      
              public void setCoordinateString(String coordinateString) {
                  this.coordinateString = coordinateString;
              }
      
              @Override
              protected void paintComponent(Graphics g) {
                  super.paintComponent(g);
      
                  Graphics2D g2d = (Graphics2D) g;
                  g2d.setColor(Color.WHITE);
                  g2d.fillRect(0, 0, getWidth(), getHeight());
      
                  g2d.setColor(Color.BLACK);
                  g2d.drawString(createLimitsString(), 10, 20);
      
                  drawXAxis(g2d, g);
                  drawYAxis(g2d, g);
                  drawCoordinate(g2d, g);
              }
      
              private String createLimitsString() {
                  String xs = String.format("%.2f", coordinateSystem.getxLimit());
                  String ys = String.format("%.2f", coordinateSystem.getyLimit());
      
                  StringBuilder builder = new StringBuilder();
                  builder.append("The actual limits are (");
                  builder.append(xs);
                  builder.append(", ");
                  builder.append(ys);
                  builder.append(")");
      
                  return builder.toString();
              }
      
              private void drawXAxis(Graphics2D g2d, Graphics g) {
                  g2d.setColor(Color.BLACK);
                  g2d.setStroke(new BasicStroke(5.0F));
                  Point p1 = coordinateSystem.convertPointToPixels(-20.0D, 0.0D);
                  Point p2 = coordinateSystem.convertPointToPixels(20.0D, 0.0D);
                  g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
      
                  g2d.setStroke(new BasicStroke(3.0F));
                  p1 = coordinateSystem.convertPointToPixels(-20.0D, -1.0D);
                  p2 = coordinateSystem.convertPointToPixels(-20.0D, 1.0D);
                  g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
      
                  Font font = getFont();
                  Point p3 = coordinateSystem.convertPointToPixels(-20.0D, -1.0D);
                  Rectangle r = new Rectangle(p3.x - 20, p3.y, 40, 20);
                  centerString(g, r, "-20.0", font);
      
                  p1 = coordinateSystem.convertPointToPixels(-10.0D, -1.0D);
                  p2 = coordinateSystem.convertPointToPixels(-10.0D, 1.0D);
                  g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
                  p3 = coordinateSystem.convertPointToPixels(-10.0D, -1.0D);
                  r = new Rectangle(p3.x - 20, p3.y, 40, 20);
                  centerString(g, r, "-10.0", font);
      
                  p1 = coordinateSystem.convertPointToPixels(10.0D, -1.0D);
                  p2 = coordinateSystem.convertPointToPixels(10.0D, 1.0D);
                  g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
                  p3 = coordinateSystem.convertPointToPixels(10.0D, -1.0D);
                  r = new Rectangle(p3.x - 20, p3.y, 40, 20);
                  centerString(g, r, "10.0", font);
      
                  p1 = coordinateSystem.convertPointToPixels(20.0D, -1.0D);
                  p2 = coordinateSystem.convertPointToPixels(20.0D, 1.0D);
                  g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
                  p3 = coordinateSystem.convertPointToPixels(20.0D, -1.0D);
                  r = new Rectangle(p3.x - 20, p3.y, 40, 20);
                  centerString(g, r, "20.0", font);
              }
      
              private void drawYAxis(Graphics2D g2d, Graphics g) {
                  g2d.setColor(Color.BLACK);
                  g2d.setStroke(new BasicStroke(5.0F));
                  Point p1 = coordinateSystem.convertPointToPixels(0.0D, -20.0D);
                  Point p2 = coordinateSystem.convertPointToPixels(0.0D, 20.0D);
                  g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
      
                  g2d.setStroke(new BasicStroke(3.0F));
                  p1 = coordinateSystem.convertPointToPixels(-1.0D, -20.0D);
                  p2 = coordinateSystem.convertPointToPixels(1.0D, -20.0D);
                  g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
      
                  Font font = getFont();
                  Point p3 = coordinateSystem.convertPointToPixels(3.0D, -20.0D);
                  Rectangle r = new Rectangle(p3.x - 20, p3.y, 40, 20);
                  centerString(g, r, "-20.0", font);
      
                  p1 = coordinateSystem.convertPointToPixels(-1.0D, -10.0D);
                  p2 = coordinateSystem.convertPointToPixels(1.0D, -10.0D);
                  g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
                  p3 = coordinateSystem.convertPointToPixels(3.0D, -10.0D);
                  r = new Rectangle(p3.x - 20, p3.y, 40, 20);
                  centerString(g, r, "-10.0", font);
      
                  p1 = coordinateSystem.convertPointToPixels(-1.0D, 10.0D);
                  p2 = coordinateSystem.convertPointToPixels(1.0D, 10.0D);
                  g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
                  p3 = coordinateSystem.convertPointToPixels(3.0D, 10.0D);
                  r = new Rectangle(p3.x - 20, p3.y, 40, 20);
                  centerString(g, r, "10.0", font);
      
                  p1 = coordinateSystem.convertPointToPixels(-1.0D, 20.0D);
                  p2 = coordinateSystem.convertPointToPixels(1.0D, 20.0D);
                  g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
                  p3 = coordinateSystem.convertPointToPixels(3.0D, 20.0D);
                  r = new Rectangle(p3.x - 20, p3.y, 40, 20);
                  centerString(g, r, "20.0", font);
              }
      
              private void drawCoordinate(Graphics2D g2d, Graphics g) {
                  if (!coordinateString.equals("")) {
                      g2d.setColor(Color.BLUE);
                      g2d.fillOval(pixelPoint.x - 5, pixelPoint.y - 5, 10, 10);
                      Font font = getFont();
                      Rectangle r = new Rectangle(pixelPoint.x - 30, pixelPoint.y,
                              60, 20);
                      centerString(g, r, coordinateString, font);
                  }
              }
      
              /**
               * This method centers a <code>String</code> in a bounding
               * <code>Rectangle</code>.
               * 
               * @param g
               *            - The <code>Graphics</code> instance.
               * @param r
               *            - The bounding <code>Rectangle</code>.
               * @param s
               *            - The <code>String</code> to center in the bounding
               *            rectangle.
               * @param font
               *            - The display font of the <code>String</code>
               * 
               * @see java.awt.Graphics
               * @see java.awt.Rectangle
               * @see java.lang.String
               */
              private void centerString(Graphics g, Rectangle r, String s, Font font) {
                  FontRenderContext frc = new FontRenderContext(null, true, true);
      
                  Rectangle2D r2D = font.getStringBounds(s, frc);
                  int rWidth = (int) Math.round(r2D.getWidth());
                  int rHeight = (int) Math.round(r2D.getHeight());
                  int rX = (int) Math.round(r2D.getX());
                  int rY = (int) Math.round(r2D.getY());
      
                  int a = (r.width / 2) - (rWidth / 2) - rX;
                  int b = (r.height / 2) - (rHeight / 2) - rY;
      
                  g.setFont(font);
                  g.drawString(s, r.x + a, r.y + b);
              }
          }
      
          private class CoordinateListener extends MouseAdapter {
      
              @Override
              public void mousePressed(MouseEvent event) {
                  drawingPanel.setPixelPoint(event.getPoint());
                  Point2D coordinatePoint = drawingPanel.getCoordinateSystem()
                          .convertToCartesian(event.getPoint());
                  drawingPanel.setCoordinatePoint(coordinatePoint);
      
                  StringBuilder builder = new StringBuilder();
      
                  if (event.getButton() == MouseEvent.BUTTON1) {
                      builder.append("(");
                      builder.append(String.format("%.2f", coordinatePoint.getX()));
                      builder.append(", ");
                      builder.append(String.format("%.2f", coordinatePoint.getY()));
                      builder.append(")");
                  } else if (event.getButton() == MouseEvent.BUTTON3) {
                      Polar2D polarPoint = drawingPanel.getCoordinateSystem()
                              .convertToPolar(event.getPoint());
      
                      builder.append("(");
                      builder.append(String.format("%.2f", polarPoint.getDistance()));
                      builder.append(", ");
                      builder.append(String.format("%.2f",
                              polarPoint.getThetaInDegrees()));
                      builder.append(")");
                  }
      
                  drawingPanel.setCoordinateString(builder.toString());
                  drawingPanel.repaint();
              }
      
          }
      
          private class SizeListener extends ComponentAdapter {
      
              @Override
              public void componentResized(ComponentEvent event) {
                  Dimension d = drawingPanel.getSize();
                  drawingPanel.getCoordinateSystem().setDrawingSize(d);
                  if (!drawingPanel.getPixelPoint().equals(new Point())) {
                      Point2D p2d = drawingPanel.getCoordinatePoint();
                      Point p = drawingPanel.getCoordinateSystem().convertToPixels(
                              p2d);
                      drawingPanel.setPixelPoint(p);
                  }
                  drawingPanel.repaint();
              }
          }
      
      }
      

      【讨论】:

        猜你喜欢
        • 2016-07-21
        • 1970-01-01
        • 1970-01-01
        • 2012-10-07
        • 1970-01-01
        • 2012-02-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多