2016-08-17 89 views
10

我正在尝试编写2D游戏引擎,并试图实现一个视口系统,以便在特定视口中绘制游戏坐标时将转换为屏幕坐标而不必手动进行转换。2D二维游戏引擎封装器

我想要做的是创建一个Graphics2D包装,增加一个setViewport方法。

我看到它的方式有2种选择:

  1. 创建具有Graphics2D的一个实例,具有所有的相同方法Graphics2DsetViewport,只是一类呼吁Graphics2D各自的方法实例。

  2. 子类Graphics2D,只是增加一个setViewport方法,然后就从Graphics2D转型为这个新类

我尝试#2#因为1显得很不切实际,但遇到了一个ClassCastException。我无法将GraphicsGraphics2D投射到这个新班级。在演员阵容之前(GraphicsGraphics2D)打印图形对象时,都会以sun.java2d.SunGraphics2D的形式出现。

我在做一些根本错误的尝试子类化和施放?如果不是,我该如何解决这个问题?

+0

我不认为任何试图继承的Graphics2D是要的任何解决方案工作得很好。 –

+0

我沿着一个大学课程的幻灯片(并非实际上课),他们说“使用setViewport()方法为Graphics2D创建包装 - 绘制视口时,在您的Graphics2D包装器中切换一个标记,每当绘制一个形状时需要转换游戏 - >屏幕坐标 - 在每个对象自己的onDraw()调用中分别进行游戏对象变换 - 完成绘制视口时取消标记包装“是否有其他一些包装的解释? –

+0

有趣 - 你有链接到这个幻灯片集合? –

回答

3

一个OO设计priciple是“在继承青睐组成”,这使用包装类装饰设计模式(这是在我看来,什么是包装在使用过程中的意思是来达到的滑动)。所以,你做了什么,其实是为一些原因优雅解决方案:

  • 它能防止今后的实施改变Graphics2D,如果您使用继承和不幸的新方法被添加到Graphics2D与与新方法相同的签名和不同的返回类型,您的类将不再编译。如果您使用相同的签名和返回类型,则可以覆盖Graphics2D中的新方法,该方法可能(并且)会导致几天令人沮丧的调试。

  • 以这种方式继承违反封装使得软件在长期运行中变得脆弱和容易出错。

  • 使用你是保护从未来的变化你的类在类的与构成组成,你的类将向前所有的方法调用它的privateGraphics2D实例,并单独处理转化坐标。

  • 它还考虑到将来很容易的扩展,使用继承将使您与目前的Graphics2D实现相关联,这会潜在地限制您的类的性能。

这样的例子存在Java API中:该Properties类扩展HashTable,这说明使用不当继承因为Properties不是一个HashTable,它并不意味着以同样的方式使用。在这种情况下,拨打Properties p.getProperty(key)可能会得到与p.get(key)不同的结果,因为后一种情况不考虑默认值。

装饰设计模式:

public class Wrapper { 
    private WrappedClass w; 

    public Wrapper(WrappedClass w) { 
     this.w = w; 
    } 

    // Forward calls to WrappedClass methods to the private instance. 
    public ReturnType example(Argument a) { return w.example(a); } 

    // Add your methods here: 
} 

虽然这似乎是一个繁琐的做法很值得在上述原因,从长远来看。 Java API中接口的存在,例如上面的HashSetSet接口,使得编写这样的类更容易,尽管我不知道Graphics2D是否存在这样的接口。

来源:有效的Java第二版 - 约书亚布洛赫

+0

+1,并被接受用于提供这种设计决策背后的逻辑推理。在基本的Graphics2D之上添加更多的功能,这绝对是开放的。谢谢! –

+0

非常欢迎! –

2

我为我写的游戏创建了一个坐标系。随意使用这些类作为例子。

以下是CoordinateSystem类。

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类。它是Point2D类的克隆。

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); 
    } 
} 
+1

吉尔伯特,感谢您的回复,并感谢您的努力和兴趣。对于赏金,虽然我正在寻找一个规范的答案,展示了如何为Graphics2D创建包装类并使用它,如OP的链接中所述。 –

1

一种选择是使用代理服务器。它可以让你包装所有的Graphics2D功能,而无需编写每种方法。

的GraphicsView接口声明的附加功能:

import java.awt.Rectangle; 

public interface GraphicsView { 
    void setViewport(Rectangle r); 
    Rectangle getViewport(); 
    boolean isViewportActive(); 
    void setViewportActive(boolean active); 
} 

的Graphics2DWrapperFactory代理到的Graphics2D + GraphicsView:

import java.awt.Graphics2D; 
import java.awt.Rectangle; 
import java.lang.reflect.InvocationHandler; 
import java.lang.reflect.Method; 
import java.lang.reflect.Proxy; 

public class Graphics2DWrapperFactory { 
    public static Graphics2D wrapGraphics2D(final Graphics2D g) { 
     GraphicsView gv = new GraphicsView() { 
      // Implement new functionality here... 
      private boolean active; 
      Rectangle r; 
      @Override 
      public Rectangle getViewport() { 
       System.err.println("getViewport called"); 
       return r; 
      } 
      @Override 
      public void setViewport(Rectangle r) { 
       this.r = r; 
       System.err.println("setViewport called"); 
      } 
      @Override 
      public boolean isViewportActive() { 
       System.err.println("isViewportActive called"); 
       return active; 
      } 
      @Override 
      public void setViewportActive(boolean active) { 
       this.active = active; 
       System.err.println("setViewportActive called"); 
      } 
     }; 
     InvocationHandler invocationHandler = new GraphicsWrapperInvocationHandler(g, gv); 
     Class<?> interfaces[] = { Graphics2D.class, GraphicsView.class}; 
     return (Graphics2D) Proxy.newProxyInstance(g.getClass().getClassLoader(), interfaces, invocationHandler); 
    } 
    private static class GraphicsWrapperInvocationHandler implements InvocationHandler { 
     private final GraphicsView gv; 
     private final Graphics2D g2d; 
     public GraphicsWrapperInvocationHandler(Graphics2D g, GraphicsView gv) { 
      this.g2d = g; 
      this.gv = gv; 
     } 
     @Override 
     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
      String methodName = method.getName(); 
      switch(methodName) { 
       // If the is calling one of the GraphicsView methods, delegate to gv 
       case "setViewport": 
       case "getViewport": 
       case "isViewportActive": 
       case "setViewportActive": 
        return method.invoke(gv, args); 
       // Otherwise, it's a Graphics2D methods. Delegate to g2d 
       default: 
        return method.invoke(g2d, args); 
      } 
     } 
    } 
}