AffineTransform.rotate() - 我怎么XLATE,旋转和缩放在同一时间? [英] AffineTransform.rotate() - how do I xlate, rotate, and scale at the same time?

查看:1437
本文介绍了AffineTransform.rotate() - 我怎么XLATE,旋转和缩放在同一时间?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下的code这确实(第一部分),我想在上面绘制了一些作品棋盘什么。

 图像pieceImage =的getImage(currentPiece);
              INT pieceHeight = pieceImage.getHeight(NULL);
              双刻度=(双)边/(双)pieceHeight;
              的AffineTransform变换=新AffineTransform();
              transform.setToTranslation(XPOS,yPos);
              transform.scale(秤,秤);
              realGraphics.drawImage(pieceImage,转换本);

这就是它得到一个棋子的图像和图像的高度,这是图像的绘制转化为广场上的一块是和图像缩放到广场的大小。

Llet说,我要旋转的黑片180度。地方我期望有这样的:

  transform.rotate(Math.toRadians(180)/ * * /?);

但我不能想出什么把X和Y.如果我把什么都没有,图像旋转,很好地绕0,0点的棋盘广场,把一块倒挂在广场上的它被认为东北是。我在X,Y的各种其它组合猜到了,没有运气呢。

我已经使用翻译把一块合适的广场,旋转变换想要另一个X,Y围绕旋转的东西,但我不知道如何告诉变换旋转件围绕一个X, y和在图像写到不同的x,y。有人能帮助我与旋转参数,或点我的东西,解释这些东西是如何工作的?我发现,没有解释他们是如何工作,到目前为止,我还没有想出如何将它们改成我的情况的东西例子...


主要编辑:除了工作code的。对不起,我不知道如何发布图片,请替换自己。

当我运行下面的我得到一个2x2的棋盘在顶部左侧车,并在右下角骑士。

如果我进入SmallChessboardComponent并采取评论delims关闭第一旋转变换说法,给我的车在其原来的位置倒过来,骑士不会出现。如果我的而不是的乘坐评论delims关闭第二变换说法,既不是一块出现在所有。

我要寻找一个办法把件倒挂在其上,他们将反正出现在广场上。我想提请每一块进入董事会;我不想code,它翻转板。

主程序:

 包为主;进口java.awt.BorderLayout中;进口javax.swing.JFrame中;进口directredraw.SmallChessboardComponent;公共类SmallChessboardMain
{
  私有静态无效DBG(字符串消息){的System.out.println(消息); }  公共静态无效的主要(字串[] args)
  {
    //创建顶层容器和内容添加到它。
    最终的JFrame帧=新的JFrame(小棋盘);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    //创建棋盘本身,并将其设置在组件
    SmallChessboard棋盘=新SmallChessboard();    //创建GUI组件将包含棋盘
    SmallChessboardComponent chessboardComponent =新SmallChessboardComponent();
    chessboardComponent.setBoard(棋盘);    frame.getContentPane()加(chessboardComponent,BorderLayout.CENTER)。    //包装和展示这一切
    frame.pack();
    frame.setVisible(真);
  }
}

棋盘类:

 包为主;公共类SmallChessboard
{
  件[] [] =方块新作品[2] [2];  公共SmallChessboard()
  {
    广场[0] [0] =新片(Piece.WHITECOLOR,Piece.ROOK);
    广场[1] [1] =新片(Piece.WHITECOLOR,Piece.KNIGHT);
  }  / **
   *拿到一块给定佐;如果返回null
   *不存在一块那里。
   * /
  公共件getPiece(INT排名,INT文件)
  {
    如果(0>秩秩||大于2 || 0>文件||文件> 2){返回NULL; }
      其他{回报广场[排名] [文件] }
  }
}

棋盘组件类:

 包directredraw;
进口java.awt.Color中;
进口java.awt.Dimension中;
进口java.awt.Graphics;
进口java.awt.Graphics2D中;
进口java.awt.Image中;
进口java.awt.Rectangle中;
进口java.awt.geom.AffineTransform中;进口javax.swing.JPanel中;进口main.Piece;
进口main.PieceImages;
进口main.SmallChessboard;
公共类SmallChessboardComponent继承JPanel
  {
    私有静态最后的serialVersionUID长1L =;    颜色whiteSquareColor = Color.yellow;
    颜色blackSquareColor = Color.blue;    私有静态无效DBG(弦乐味精){的System.out.println(MSG); }    私人SmallChessboard棋盘= NULL;    //目前与旋转图像播放;这仿射变换
    //应该帮助
    的AffineTransform rotationTransform = NULL;    私人最终诠释DEFAULT_ preFERRED_SIDE = 400;
    INT wholeSide = DEFAULT_ preFERRED_SIDE;
    INT侧= DEFAULT_ preFERRED_SIDE / 8;    公共无效setBoard(SmallChessboard givenBoard)
    {棋盘= givenBoard;
    }    / **
     *可设置一个或两个颜色为这个棋盘;如果任一方
     *参数为NULL,他们不会改变现有的颜色
     * 设置。
     * /
    公共无效setColors(彩色darkSquare,颜色lightSquare)
    {
      如果(darkSquare!= NULL){blackSquareColor = darkSquare; }
      如果(lightSquare!= NULL){whiteSquareColor = lightSquare; }
    }    / **
     *返回preferred大小此component.s
     * /
    公共尺寸的get preferredSize()
    {返回新尺寸(wholeSide,wholeSide);
    }    / *
     *返回图像对象为给定片
     * /
    私人形象的getImage(一块一块)
    {返回PieceImages.getPieceImage(这一点,片);
    }    公共无效的paintComponent(图形图像)
    {
      Graphics2D的realGraphics =(Graphics2D的)显卡;      //图像容器可能被拉伸。
      //计算当前容器举办的规模最大的广场,
      //然后该尺寸为单个正方形的1/2。
      INT wholeWidth = this.getWidth();
      INT wholeHeight = this.getHeight();
      wholeSide =(wholeWidth / 2)* 2;
      如果(wholeHeight&下; wholeWidth){wholeSide =(wholeHeight / 2)* 2; }
      侧= wholeSide / 2;      矩形夹= realGraphics.getClipBounds();
      布尔firstColumnWhite = FALSE;      //为电路板上的每个文件:
      //机顶盒方是否属于白色人种
      根据白/黑色方形//设置背景颜色
      //
      对(INT fileIndex = 0; fileIndex&下; 8; fileIndex ++)
        {布尔currentColorWhite = firstColumnWhite;
          firstColumnWhite = firstColumnWhite!;          //绘制电路板和所有的作品
          INT rankIndex = 2;
          为(rankIndex = 2; rankIndex> = 0; rankIndex--)
          {            !currentColorWhite = currentColorWhite;            // x和我们绘制正方形的左​​上角的y位置,
            //和矩形变得尺寸和方本身的位置。
            INT XPOS = fileIndex *的一面;
            INT yPos = rankIndex *的一面;
            矩形RECT =新的Rectangle(XPOS,yPos,边,面);            //如果这个广场相交,我们正在绘制剪切的矩形,
            //然后我们会绘制广场和广场上的棋子。
            如果(rect.intersects(夹))
            {
              //这个放下正方形的正确的颜色
              如果(currentColorWhite){realGraphics.setColor(whiteSquareColor); }
                                其他{realGraphics.setColor(blackSquareColor); }
              realGraphics.fillRect(XPOS,yPos,边,面);              //如果在这个广场的一块,它是不是在选
              //片刻,然后绘制它。
              一块currentPiece = chessboard.getPiece(rankIndex,fileIndex);
              如果(currentPiece!= NULL)
                {
                  图片pieceImage =的getImage(currentPiece);
                  INT pieceHeight = pieceImage.getHeight(NULL);
                  双scalePiece =(双)边/(双)pieceHeight;
                  的AffineTransform变换=新AffineTransform();
// transform.setToRotation(Math.toRadians(180));
                  transform.setToRotation(Math.toRadians(180),边/ 2,边/ 2);
                  transform.scale(scalePiece,scalePiece);
                  transform.translate(XPOS / scalePiece,yPos / scalePiece);
//如果(currentPiece.isBlack())
// {
// transform.translate(XPOS +(侧+ 2),yPos +(侧+ 2));
// transform.rotate(Math.toRadians(180)/ *,* /);
//}
//其他
// {
// transform.translate(XPOS,yPos);
//}
                  realGraphics.drawImage(pieceImage,转换本);
                }
            }
          }
        }
    }
  }

Piece.java

 包为主;公共类件
{
  //片类型;片类型和的总和
  //颜色给出了一些特有的两个类型和颜色,
  //这是用于诸如图像索引。
  公共静态最终诠释PAWN = 0;
  公共静态最终诠释KNIGHT = 1;
  公共静态最终诠释BISHOP = 2;
  公共静态最终诠释ROOK = 3;
  公共静态最终诠释QUEEN = 4;
  公共静态最终诠释KING = 5;  这些//一个是当前块的颜色
  公共静态最终诠释NOCOLOR = -1;
  //片类型和的总和
  //颜色给出了一些特有的两个类型和颜色,
  //这是用于诸如图像索引。
  公共静态最终诠释BLACKCOLOR = 0;
  公共静态最终诠释WHITECOLOR = 6;  INT颜色= NOCOLOR;
  INT imageIndex指定;  公共件(INT颜色,诠释pieceType)
  {
    // DBG - 所有作品都是白色的乌鸦现在...
    this.color =颜色;
    = imageIndex指定颜色+ pieceType;
  }  / **
   *返回这片的颜色相关联的整数;
   * /
  INT getPieceColor()
  {返回颜色;
  }  / **
   *返回真,如果一块是黑色的
   * /
  公共布尔isBlack()
  {
    回报(颜色== BLACKCOLOR);
  }  / **
   *设置这片相关的颜色;常量
   *在这个类中。
   * /
  公共无效setPieceColor(INT givenColor)
  {颜色= givenColor;
  }  / **
   *返回指定用于此片图像的整数。
   * /
  INT getImageIndex()
  {返回imageIndex指定;
  }}

和PieceImages.java

 包为主;进口java.awt.Component中;
进口java.awt.Image中;
进口java.awt.MediaTracker中;
进口java.awt.Toolkit中;
进口的java.net.URL;公共类PieceImages
{静态图像图像[] = NULL;私有静态无效DBG(弦乐味精){的System.out.println(MSG); }  公共静态图像getPieceImage(Component目标,一块一块)
  {
    如果(图片== NULL)
    尝试
    {
      媒体跟踪器跟踪器=新媒体跟踪(目标);
      照片=新的图像[12];
      图像[Piece.BLACKCOLOR + Piece.PAWN] =的getImage(跟踪器bPawn.gif);
      图像[Piece.BLACKCOLOR + Piece.KNIGHT] =的getImage(跟踪器bKnight.gif);
      图像[Piece.BLACKCOLOR + Piece.BISHOP] =的getImage(跟踪器bBishop.gif);
      图像[Piece.BLACKCOLOR + Piece.ROOK] =的getImage(跟踪器bRook.gif);
      图像[Piece.BLACKCOLOR + Piece.QUEEN] =的getImage(跟踪器bQueen.gif);
      图像[Piece.BLACKCOLOR + Piece.KING] =的getImage(跟踪器bKing.gif);      图像[Piece.WHITECOLOR + Piece.PAWN] =的getImage(跟踪器wPawn.gif);
      图像[Piece.WHITECOLOR + Piece.KNIGHT] =的getImage(跟踪器wKnight.gif);
      图像[Piece.WHITECOLOR + Piece.BISHOP] =的getImage(跟踪器wBishop.gif);
      图像[Piece.WHITECOLOR + Piece.ROOK] =的getImage(跟踪器wRook.gif);
      图像[Piece.WHITECOLOR + Piece.QUEEN] =的getImage(跟踪器wQueen.gif);
      图像[Piece.WHITECOLOR + Piece.KING] =的getImage(跟踪器wKing.gif);
      如果(!tracker.waitForAll(10000))
      {的System.out.println(错误:不是所有的片装main.images);
      }
      DBG(一张图片加载);
    }
    赶上(例外XCP)
    {的System.out.println(错误加载图像);
      xcp.printStackTrace();
    }
    返回图像[piece.getImageIndex()];
  }  私有静态图像的getImage(媒体跟踪器跟踪器,字符串的文件)
  {
    网址URL = PieceImages.class.getResource(图像/+文件);
    形象画像= Toolkit.getDefaultToolkit()的getImage(URL)。
    tracker.addImage(图像,1);
    返回形象;
  }
}


解决方案

好吧,这是一个小戏法。这个例子code将仅适用于90度的增量工作(它只是这样设计),做小的增量,您可以使用一些触发计算图像的宽度和高度(有一个答案的地方要做到这;))

 公共类ImagePane继承JPanel {    私人的BufferedImage MASTERIMAGE;
    私人的BufferedImage的RenderedImage;    公共ImagePane(BufferedImage的图像){
        MASTERIMAGE =图像;
        applyRotation(0);
    }    @覆盖
    公共尺寸的get preferredSize(){
        返回新的Dimension(renderedImage.getWidth(),renderedImage.getHeight());
    }    @覆盖
    公共尺寸getMinimumSize的(){
        得到的回报preferredSize();
    }    保护INT getVirtualAngle(INT角){
        浮动fRotations =(浮点)角/ 360F;
        INT转=(int)的(fRotations - (fRotations / 1000));        INT虚拟=角 - (转* 360);        如果(虚拟​​℃,){
            虚拟= 360 +虚;
        }        返回虚;
    }    公共无效applyRotation(INT角){
        //这将只对90度角...        //规范化的角度,以确保它是唯一0-360度之间
        INT virtualAngle = getVirtualAngle(角度);
        尺寸大小=新的Dimension(masterImage.getWidth(),masterImage.getHeight());
        INT masterWidth = masterImage.getWidth();
        INT masterHeight = masterImage.getHeight();        双X = 0; // masterWidth / 2.0;
        双Y = 0; // masterHeight / 2.0;        开关(virtualAngle){
            情况下0:
                打破;
            案例180:
                打破;
            案例90:
            案例270:
                大小=新的Dimension(masterImage.getHeight(),masterImage.getWidth());
                X =(masterHeight - masterWidth)/ 2.0;
                Y =(masterWidth - masterHeight)/ 2.0;
                打破;
        }
        的RenderedImage =新的BufferedImage(size.width,size.height,masterImage.getTransparency());
        Graphics2D的G2D = renderedImage.createGraphics();        的AffineTransform在= AffineTransform.getTranslateInstance(X,Y);        at.rotate(Math.toRadians(virtualAngle),masterWidth / 2.0,masterHeight / 2.0);
        g2d.drawImage(MASTERIMAGE在,NULL);        g2d.dispose();
    }    @覆盖
    保护无效paintComponent(图形G){
        super.paintComponent方法(G);        Graphics2D的G2D =(Graphics2D的)克;
        INT宽度=的getWidth() - 1;
        INT高度=的getHeight() - 1;        INT X =(宽 - renderedImage.getWidth())/ 2;
        INT Y =(身高 - renderedImage.getHeight())/ 2;        g2d.drawImage(的RenderedImage,X,Y,这一点);
    }}

现在,你可以简单地翻转的形象垂直,如果这样可以更好地为您

 公共类FlipPane继承JPanel {    私人的BufferedImage MASTERIMAGE;
    私人的BufferedImage的RenderedImage;    公共FlipPane(BufferedImage的图像){
        MASTERIMAGE =图像;
        flipMaster();
    }    @覆盖
    公共尺寸的get preferredSize(){
        返回新的Dimension(renderedImage.getWidth(),renderedImage.getHeight());
    }    @覆盖
    公共尺寸getMinimumSize的(){
        得到的回报preferredSize();
    }    保护无效flipMaster(){
        的RenderedImage =新的BufferedImage(masterImage.getWidth(),masterImage.getHeight(),masterImage.getTransparency());
        Graphics2D的G2D = renderedImage.createGraphics();
        g2d.setTransform(AffineTransform.getScaleInstance(1,-1));
        g2d.drawImage(MASTERIMAGE,0,-masterImage.getHeight(),这一点);
        g2d.dispose();
    }    @覆盖
    保护无效paintComponent(图形G){
        super.paintComponent方法(G);        Graphics2D的G2D =(Graphics2D的)克;
        INT宽度=的getWidth() - 1;
        INT高度=的getHeight() - 1;        INT X =(宽 - renderedImage.getWidth())/ 2;
        INT Y =(身高 - renderedImage.getHeight())/ 2;        g2d.drawImage(的RenderedImage,X,Y,这一点);
    }
}

这主要结果是:

原图| 180度旋转|垂直反转...

现在,如果你改变了 flipMaster 方法来读取:

  g2d.setTransform(AffineTransform.getScaleInstance(-1,-1));
g2d.drawImage(MASTERIMAGE,-masterImage.getWidth(),-masterImage.getHeight(),这一点);

您会得到相同的效果,在180°旋转;)

I have the following code which does (the first part of) what I want drawing a chessboard with some pieces on it.

              Image pieceImage = getImage(currentPiece);
              int pieceHeight = pieceImage.getHeight(null);
              double scale = (double)side/(double)pieceHeight;
              AffineTransform transform = new AffineTransform();
              transform.setToTranslation(xPos, yPos);
              transform.scale(scale, scale);
              realGraphics.drawImage(pieceImage, transform, this);

that is, it gets a chess piece's image and the image's height, it translates the drawing of that image to the square the piece is on and scales the image to the size of the square.

Llet's say I want to rotate the black pieces 180 degrees. Somewhere I expect to have something like:

transform.rotate(Math.toRadians(180) /* ?, ? */);

But I can't figure out what to put in as X and Y. If I put nothing, the image is nicely rotated around the 0,0 point of its chessboard square, putting the piece upside down in the square to the northeast of where it is supposed to be. I've guessed at various other combinations of x,y, with no luck yet.

I am already using translation to put the piece in the right square, the rotation transform wants another x,y around which to rotate things, but I don't know how to tell the transform to rotate the piece around one x,y and write the image to a different x,y. Can someone help me with the rotation parameters, or point me to something that explains how these things work? I've found examples of things that don't explain how they work, and so far I haven't figured out how to alter them to my situation...


Major edit: addition of working code. Sorry, I don't know how to post images, please substitute your own.

When I run the following I get a 2x2 chess board with a rook at the top left and a knight at the bottom right.

If I go into SmallChessboardComponent and take the comment delims off the first rotation transform statement, I get the rook in its original place upside down and the knight does not appear. If I instead take the comment delims off the second transform statement, neither piece appears at all.

I am looking for a way to turn the pieces upside down on the square on which they would appear anyway. I want to draw each piece onto the board; I don't want code that flips the board.

main program:

package main;

import java.awt.BorderLayout;

import javax.swing.JFrame;

import directredraw.SmallChessboardComponent;

public class SmallChessboardMain
{
  private static void dbg (String message) { System.out.println(message); }

  public static void main(String[] args)
  {
    //Create the top-level container and add contents to it.
    final JFrame frame = new JFrame("Small Chessboard");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    // create the chessboard itself and set it in the component
    SmallChessboard chessboard = new SmallChessboard();

    // create the GUI component that will contain the chessboard
    SmallChessboardComponent chessboardComponent = new SmallChessboardComponent();
    chessboardComponent.setBoard (chessboard);

    frame.getContentPane().add(chessboardComponent, BorderLayout.CENTER);

    // pack and display all this
    frame.pack();
    frame.setVisible(true);
  }
}

chessboard class:

package main;

public class SmallChessboard
{
  Piece [][] squares = new Piece[2][2];

  public SmallChessboard()
  {
    squares[0][0] = new Piece(Piece.WHITECOLOR, Piece.ROOK);
    squares[1][1] = new Piece(Piece.WHITECOLOR, Piece.KNIGHT);
  }

  /**
   * get the piece at the given rank and file; null if
   * no piece exists there.
   */
  public Piece getPiece(int rank, int file)
  { 
    if (0 > rank || rank > 2 || 0 > file || file > 2) { return null; }
      else { return squares[rank][file]; }
  }
}

chessboard component class:

package directredraw;


import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;

import javax.swing.JPanel;

import main.Piece;
import main.PieceImages;
import main.SmallChessboard;


public class SmallChessboardComponent extends JPanel
  { 
    private static final long serialVersionUID = 1L;

    Color whiteSquareColor = Color.yellow;
    Color blackSquareColor = Color.blue;

    private static void dbg (String msg) { System.out.println(msg); }

    private SmallChessboard  chessboard = null;

    // currently playing with rotating images; this affine transform
    // should help
    AffineTransform rotationTransform = null;

    private final int DEFAULT_PREFERRED_SIDE = 400;
    int wholeSide = DEFAULT_PREFERRED_SIDE;
    int side = DEFAULT_PREFERRED_SIDE / 8;

    public void setBoard (SmallChessboard givenBoard)
    { chessboard = givenBoard;
    }

    /**
     * set either or both colors for this chessboard; if either of
     * the arguments are null, they do not change the existing color
     * setting.
     */
    public void setColors (Color darkSquare, Color lightSquare)
    {
      if (darkSquare != null) { blackSquareColor = darkSquare; }
      if (lightSquare != null) { whiteSquareColor = lightSquare; }
    }

    /**
     * return the preferred size for this component.s
     */
    public Dimension getPreferredSize()
    { return new Dimension(wholeSide, wholeSide);
    }

    /*
     * return the image object for the given piece
     */
    private Image getImage(Piece piece)
    { return PieceImages.getPieceImage(this, piece);
    }

    public void paintComponent (Graphics graphics)
    {
      Graphics2D realGraphics = (Graphics2D) graphics;

      // the image container might have been stretched.
      // calculate the largest square held by the current container,
      // and then 1/2 of that size for an individual square.
      int wholeWidth  = this.getWidth();
      int wholeHeight = this.getHeight();
      wholeSide   = (wholeWidth / 2) * 2;
      if (wholeHeight < wholeWidth) { wholeSide = (wholeHeight / 2) * 2; }
      side = wholeSide / 2; 

      Rectangle clip = realGraphics.getClipBounds();
      boolean firstColumnWhite = false;

      // for each file on the board:
      //    set whether top square is white
      //    set background color according to white/black square
      //    
      for (int fileIndex=0; fileIndex<8; fileIndex++)
        { boolean currentColorWhite = firstColumnWhite;
          firstColumnWhite = !firstColumnWhite;

          // draw the board and all the pieces
          int rankIndex = 2;
          for (rankIndex=2; rankIndex>=0; rankIndex--)
          { 

            currentColorWhite = !currentColorWhite;

            // x and y position of the top left corner of the square we're drawing,
            // and rect becomes the dimensions and position of the square itself.
            int xPos = fileIndex * side;
            int yPos = rankIndex * side;
            Rectangle rect = new Rectangle(xPos, yPos, side, side);

            // if this square intersects the clipping rectangle we're drawing,
            // then we'll draw the square and the piece on the square.
            if (rect.intersects(clip))
            {
              // this puts down the correct color of square 
              if (currentColorWhite) { realGraphics.setColor(whiteSquareColor); }
                                else { realGraphics.setColor(blackSquareColor); }
              realGraphics.fillRect(xPos, yPos, side, side); 

              // if there is a piece on this square and it isn't selected at the
              // moment, then draw it.
              Piece currentPiece = chessboard.getPiece(rankIndex, fileIndex);
              if (currentPiece != null)
                { 
                  Image pieceImage = getImage(currentPiece);
                  int pieceHeight = pieceImage.getHeight(null);
                  double scalePiece = (double)side/(double)pieceHeight;
                  AffineTransform transform = new AffineTransform();
//                  transform.setToRotation(Math.toRadians(180));
                  transform.setToRotation(Math.toRadians(180), side/2, side/2);
                  transform.scale(scalePiece, scalePiece);
                  transform.translate(xPos/scalePiece, yPos/scalePiece);
//                  if (currentPiece.isBlack()) 
//                  {
//                    transform.translate(xPos + (side+2), yPos + (side+2));
//                    transform.rotate(Math.toRadians(180) /*, ,*/ ); 
//                  }
//                  else
//                  {
//                    transform.translate(xPos, yPos);
//                  }
                  realGraphics.drawImage(pieceImage, transform, this);
                }
            }
          }
        }
    }
  }

Piece.java

package main;

public class Piece
{ 
  // piece types; the sum of the piece type and the
  // color gives a number unique to both type and color,
  // which is used for things like image indices.
  public static final int PAWN   = 0;
  public static final int KNIGHT = 1;
  public static final int BISHOP = 2;
  public static final int ROOK   = 3;
  public static final int QUEEN  = 4;
  public static final int KING   = 5;

  // one of these is the color of the current piece
  public static final int NOCOLOR = -1;
  // the sum of the piece type and the
  // color gives a number unique to both type and color,
  // which is used for things like image indices.
  public static final int BLACKCOLOR = 0;
  public static final int WHITECOLOR = 6;

  int color = NOCOLOR;
  int imageIndex;

  public Piece(int color, int pieceType)
  { 
    // dbg -- all pieces are white rooks for now...
    this.color  = color;
    imageIndex  = color + pieceType;
  }

  /**
   * return the integer associated with this piece's color;
   */
  int getPieceColor()
  { return color;
  }

  /**
   * return true if the piece is black
   */
  public boolean isBlack() 
  { 
    return (color == BLACKCOLOR); 
  }

  /**
   * set the color associated with this piece; constants
   * found in this class.
   */
  public void setPieceColor(int givenColor)
  { color = givenColor;
  }

  /**
   * return the integer designated for the image used for this piece.
   */
  int getImageIndex()
  { return imageIndex;
  }

}

and PieceImages.java

package main;

import java.awt.Component;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Toolkit;
import java.net.URL;

public class PieceImages
{ static Image images[] = null;

private static void dbg (String msg) { System.out.println(msg); } 

  public static Image getPieceImage (Component target, Piece piece)
  {
    if (images == null)
    try
    { 
      MediaTracker tracker = new MediaTracker(target);
      images = new Image[12];
      images[Piece.BLACKCOLOR + Piece.PAWN] = getImage(tracker, "bPawn.gif");
      images[Piece.BLACKCOLOR + Piece.KNIGHT] = getImage(tracker, "bKnight.gif");
      images[Piece.BLACKCOLOR + Piece.BISHOP] = getImage(tracker, "bBishop.gif");
      images[Piece.BLACKCOLOR + Piece.ROOK] = getImage(tracker, "bRook.gif");
      images[Piece.BLACKCOLOR + Piece.QUEEN] = getImage(tracker, "bQueen.gif");
      images[Piece.BLACKCOLOR + Piece.KING] = getImage(tracker, "bKing.gif");

      images[Piece.WHITECOLOR + Piece.PAWN] = getImage(tracker, "wPawn.gif");
      images[Piece.WHITECOLOR + Piece.KNIGHT] = getImage(tracker, "wKnight.gif");
      images[Piece.WHITECOLOR + Piece.BISHOP] = getImage(tracker, "wBishop.gif");
      images[Piece.WHITECOLOR + Piece.ROOK] = getImage(tracker, "wRook.gif");
      images[Piece.WHITECOLOR + Piece.QUEEN] = getImage(tracker, "wQueen.gif");
      images[Piece.WHITECOLOR + Piece.KING] = getImage(tracker, "wKing.gif");
      if (!tracker.waitForAll(10000))
      { System.out.println("ERROR: not all piece main.images loaded");
      }
      dbg("piece images loaded");
    }
    catch (Exception xcp)
    { System.out.println("Error loading images");
      xcp.printStackTrace();
    }
    return images[piece.getImageIndex()];
  }

  private static Image getImage(MediaTracker tracker, String file)
  {
    URL url = PieceImages.class.getResource("images/" + file);
    Image image = Toolkit.getDefaultToolkit().getImage(url);
    tracker.addImage(image,  1);
    return image;
  }
}

解决方案

Okay, this is a little slight of hand. The example code will only work for 90 degree increments (it was only designed this way), to do smaller increments you to use some trig to calculate the image width and height (there's a answer somewhere for that to ;))

public class ImagePane extends JPanel {

    private BufferedImage masterImage;
    private BufferedImage renderedImage;

    public ImagePane(BufferedImage image) {
        masterImage = image;
        applyRotation(0);
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(renderedImage.getWidth(), renderedImage.getHeight());
    }

    @Override
    public Dimension getMinimumSize() {
        return getPreferredSize();
    }

    protected int getVirtualAngle(int angle) {
        float fRotations = (float) angle / 360f;
        int rotations = (int) (fRotations - (fRotations / 1000));

        int virtual = angle - (rotations * 360);

        if (virtual < 0) {
            virtual = 360 + virtual;
        }

        return virtual;
    }

    public void applyRotation(int angle) {
        // This will only work for angles of 90 degrees...

        // Normalize the angle to make sure it's only between 0-360 degrees
        int virtualAngle = getVirtualAngle(angle);
        Dimension size = new Dimension(masterImage.getWidth(), masterImage.getHeight());
        int masterWidth = masterImage.getWidth();
        int masterHeight = masterImage.getHeight();

        double x = 0; //masterWidth / 2.0;
        double y = 0; //masterHeight / 2.0;

        switch (virtualAngle) {
            case 0:
                break;
            case 180:
                break;
            case 90:
            case 270:
                size = new Dimension(masterImage.getHeight(), masterImage.getWidth());
                x = (masterHeight - masterWidth) / 2.0;
                y = (masterWidth - masterHeight) / 2.0;
                break;
        }
        renderedImage = new BufferedImage(size.width, size.height, masterImage.getTransparency());
        Graphics2D g2d = renderedImage.createGraphics();

        AffineTransform at = AffineTransform.getTranslateInstance(x, y);

        at.rotate(Math.toRadians(virtualAngle), masterWidth / 2.0, masterHeight / 2.0);
        g2d.drawImage(masterImage, at, null);

        g2d.dispose();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D) g;
        int width = getWidth() - 1;
        int height = getHeight() - 1;

        int x = (width - renderedImage.getWidth()) / 2;
        int y = (height - renderedImage.getHeight()) / 2;

        g2d.drawImage(renderedImage, x, y, this);
    }

}

Now, you could simply "flip" the image vertically, if that works better for you

public class FlipPane extends JPanel {

    private BufferedImage masterImage;
    private BufferedImage renderedImage;

    public FlipPane(BufferedImage image) {
        masterImage = image;
        flipMaster();
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(renderedImage.getWidth(), renderedImage.getHeight());
    }

    @Override
    public Dimension getMinimumSize() {
        return getPreferredSize();
    }

    protected void flipMaster() {
        renderedImage = new BufferedImage(masterImage.getWidth(), masterImage.getHeight(), masterImage.getTransparency());
        Graphics2D g2d = renderedImage.createGraphics();
        g2d.setTransform(AffineTransform.getScaleInstance(1, -1));
        g2d.drawImage(masterImage, 0, -masterImage.getHeight(), this);
        g2d.dispose();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D) g;
        int width = getWidth() - 1;
        int height = getHeight() - 1;

        int x = (width - renderedImage.getWidth()) / 2;
        int y = (height - renderedImage.getHeight()) / 2;

        g2d.drawImage(renderedImage, x, y, this);
    }
}

This basically results in:

Original | 180 degree rotation | Vertical inversion...

Now, if you change the flipMaster method to read:

g2d.setTransform(AffineTransform.getScaleInstance(-1, -1));
g2d.drawImage(masterImage, -masterImage.getWidth(), -masterImage.getHeight(), this);

You'll get the same effect as the 180 rotation ;)

这篇关于AffineTransform.rotate() - 我怎么XLATE,旋转和缩放在同一时间?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆