1

我想建立一个从 (-1, -1) 到 (+1, +1) 的数学坐标空间(其中 y 向上而不是向下),并且无论窗口大小如何,它都适合窗口。

我在 Java SE 7 中使用匿名 JComponent 子类并将传入Graphics的内容paintComponent转换为Graphics2D然后在Graphics2D

但是Graphics2D被设置为随窗口大小而变化的计算机坐标空间。如何让它根据窗口大小重新缩放并让 Y 向上?以下程序应在右上象限显示一个黑色方块。

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;

import javax.swing.JComponent;
import javax.swing.JFrame;

public class G {
  public static void main (String [] args) {
    JFrame frame = new JFrame(G.class.getCanonicalName());
    frame.setUndecorated(true);
    JComponent component = new JComponent() {
      private static final long serialVersionUID = 1L;
      @Override
      protected void paintComponent (Graphics g) {
        super.paintComponent(g);
        paint2D((Graphics2D)g);
      }
      protected void paint2D (Graphics2D g2) {
        g2.draw(new Rectangle2D.Double(0.1, 0.1, 0.9, 0.9));
      }
    };
    frame.add(component);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(400, 400);
    frame.setVisible(true);
  }
}
4

1 回答 1

6

transform()使用和设置您想要的坐标系translate()。所以:

  1. 您希望原点位于(0,高度);左下方。
  2. 然后你想翻转 Y 轴。

示例代码:

AffineTransform tform = AffineTransform.getTranslateInstance( 0, height);
tform.scale( 1, -1);
g2.setTransform( tform);

[我的编辑版本]:

public static void main (String [] args) {
    JFrame frame = new JFrame( G2dTransform_Question.class.getCanonicalName());
    JComponent component = new JComponent() {
        private static final long serialVersionUID = 1L;
        @Override
        protected void paintComponent (Graphics g) {
            super.paintComponent(g);
            paint2D((Graphics2D)g);
        }
        protected void paint2D (Graphics2D g2) {
            AffineTransform tform = AffineTransform.getTranslateInstance( 0, getHeight());
            tform.scale( getWidth(), -getHeight());    // NOTE -- to make 1.0 'full width'.
            g2.setTransform( tform);

            g2.setColor( Color.BLUE);  // NOTE -- so we can *see* something.
            g2.fill( new Rectangle2D.Double(0.1, 0.1, 0.8, 0.8));  // NOTE -- 'fill' works better than 'draw'.
        }
    };

    frame.setLayout( new BorderLayout());    // NOTE -- make the component size to frame.
    frame.add( component, BorderLayout.CENTER);

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(400, 400);
    frame.setVisible(true);
}

【气垫船版】:谢谢Hover!

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;

import javax.swing.JComponent;
import javax.swing.JFrame;

public class G {
  public static final int PREF_W = 400;
  public static final int PREF_H = PREF_W;

public static void main (String [] args) {
    JFrame frame = new JFrame(G.class.getCanonicalName());
    frame.setUndecorated(true);
    JComponent component = new JComponent() {
      private static final long serialVersionUID = 1L;
      @Override
      protected void paintComponent (Graphics g) {
        super.paintComponent(g);
        AffineTransform tform = AffineTransform.getTranslateInstance( 0, getHeight());
        tform.scale( 1, -1);
        Graphics2D g2 = (Graphics2D) g.create();
        g2.setTransform( tform);
        paint2D(g2);
        g2.dispose();
      }
      protected void paint2D (Graphics2D g2) {
        g2.draw(new Rectangle2D.Double(10, 10, 20, 30));
      }

      @Override
      public Dimension getPreferredSize() {
         return new Dimension(PREF_W, PREF_H);
      }
    };
    frame.add(component);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack();
    frame.setVisible(true);
  }
}
于 2013-05-14T02:18:46.303 回答