[英]Using Affine Transform on Graphics2D Objects
I am new to AffineTransform but I spent a couple of hours and kind of figured out how to get it to do what I want. 我是AffineTransform的新手,但是我花了几个小时,并弄清楚了如何使它完成我想做的事情。 Basically my goal is the make a JInternal Frame that scales the Graphics2D objects when it is minimized. 基本上,我的目标是制作一个JInternal Frame,以在最小化Graphics2D对象时缩放该对象。 For proof of concept I have created some code that scales with the mouse wheel and is translated on a mouse drag. 为了概念验证,我创建了一些代码,该代码可随鼠标滚轮缩放并在鼠标拖动时进行翻译。
My question is, how can I package this into a JInternalFrame that scales when the JInternalFrame is minimized? 我的问题是,如何将其打包到最小化JInternalFrame时可缩放的JInternalFrame中? Also, is there a better way to do what I want to do? 另外,是否有更好的方法来做我想做的事?
Self contained example: 自包含的示例:
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class AffineTransformTest {
private static TransformingCanvas canvas;
public static void main(String[] args) {
TransformingCanvas.initializePointList();
JFrame frame = new JFrame();
canvas = new TransformingCanvas(TransformingCanvas.POINT_LIST);
TranslateHandler translator = new TranslateHandler();
canvas.addMouseListener(translator);
canvas.addMouseMotionListener(translator);
canvas.addMouseWheelListener(new ScaleHandler());
frame.setLayout(new BorderLayout());
frame.getContentPane().add(canvas, BorderLayout.CENTER);
frame.setSize(750, 750);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setVisible(true);
}
private static class TransformingCanvas extends JComponent {
private double translateX;
private double translateY;
private double scale;
private final int PREF_W = 800; //Window width
private final int PREF_H = 800; //Window height
private static final Color INACTIVE_COLOR = Color.RED;
private static final Color ACTIVE_COLOR = Color.green;
private java.util.List<Point> points;
private java.util.List<Ellipse2D> ellipses = new ArrayList<>();
private Map<Ellipse2D, Color> ellipseColorMap = new HashMap<>();
public static java.util.List<Point> POINT_LIST = new ArrayList<>();
/*
* This loop will initialize POINT_LIST with the set of points for drawing the ellipses.
* The for each loop initializes points for the top row and the second for loop draws the
* right triangle.
*/
protected static void initializePointList() {
int ellipsePointsYCoordinate[] = {140, 200, 260, 320, 380, 440, 500, 560, 620};
int ellipsePointsXCoordinate[] = {140, 200, 260, 320, 380, 440, 500, 560, 620, 680};
int xx = 80;
for (int aXt : ellipsePointsXCoordinate) {
POINT_LIST.add(new Point(aXt, xx));
}
for (int i = 0; i < ellipsePointsYCoordinate.length; i++) {
for (int j = i; j < ellipsePointsYCoordinate.length; j++) {
POINT_LIST.add(new Point(ellipsePointsXCoordinate[i], ellipsePointsYCoordinate[j]));
}
}
}
TransformingCanvas() {
translateX = 0;
translateY = 0;
scale = 1;
setOpaque(true);
setDoubleBuffered(true);
}
public TransformingCanvas(java.util.List<Point> points) {
this.points = points;
int OVAL_WIDTH = 30;
for (Point p : points) {
int x = p.x - OVAL_WIDTH / 2;
int y = p.y - OVAL_WIDTH / 2;
int w = OVAL_WIDTH;
int h = OVAL_WIDTH;
Ellipse2D ellipse = new Ellipse2D.Double(x, y, w, h);
ellipses.add(ellipse);
ellipseColorMap.put(ellipse, INACTIVE_COLOR);
}
}
@Override public void paint(Graphics g) {
AffineTransform tx = new AffineTransform();
tx.translate(translateX, translateY);
tx.scale(scale, scale);
Graphics2D g2 = (Graphics2D) g;
g2.fillRect(0,0, getWidth(), getHeight());
g2.setTransform(tx);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
for (Ellipse2D ellipse : ellipses) {
g2.setColor(ellipseColorMap.get(ellipse));
g2.fill(ellipse);
g2.setColor(Color.BLACK);
g2.setStroke(new BasicStroke(2));
g2.draw(ellipse);
}
/*
* Set the font characteristics, color, and draw the row labels.
*/
g.setFont(new Font("TimesRoman", Font.BOLD, 18));
g.setColor(Color.BLACK);
//NOTE to self: add label DrawStrings back
//Draws a 3DRect around the top row of ellipse2D objects
g2.setColor(Color.lightGray);
g2.draw3DRect(120, 60, 580, 40, true);
g2.draw3DRect(121, 61, 578, 38, true);
g2.draw3DRect(122, 62, 576, 36, true);
//super.paint(g);
}
}
private static class TranslateHandler implements MouseListener,
MouseMotionListener {
private int lastOffsetX;
private int lastOffsetY;
public void mousePressed(MouseEvent e) {
// capture starting point
lastOffsetX = e.getX();
lastOffsetY = e.getY();
}
public void mouseDragged(MouseEvent e) {
// new x and y are defined by current mouse location subtracted
// by previously processed mouse location
int newX = e.getX() - lastOffsetX;
int newY = e.getY() - lastOffsetY;
// increment last offset to last processed by drag event.
lastOffsetX += newX;
lastOffsetY += newY;
// update the canvas locations
canvas.translateX += newX;
canvas.translateY += newY;
// schedule a repaint.
canvas.repaint();
}
public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mouseMoved(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
}
private static class ScaleHandler implements MouseWheelListener {
public void mouseWheelMoved(MouseWheelEvent e) {
if(e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) {
// make it a reasonable amount of zoom
// .1 gives a nice slow transition
canvas.scale += (.1 * e.getWheelRotation());
// don't cross negative threshold.
// also, setting scale to 0 has bad effects
canvas.scale = Math.max(0.00001, canvas.scale);
canvas.repaint();
}
}
}
}
I don't fully get why you would want to scale the Graphics
when they're not visible, but here is a rough instruction how to do it: 我不完全理解为什么您希望在不可见的Graphics
时缩放它们,但是这里有一个粗略的说明:
JDesktopPane
as the JFrame
's contentpane. 将JDesktopPane
设置为JFrame
的contentpane。 JInternalFrame
and add it do the JDesktopPane
创建一个JInternalFrame
并将其添加到JDesktopPane
InternalFrameListener
to the internal frame and then you can put inside the public void internalFrameIconified(InternalFrameEvent arg0)
method everything you want to do if the internal frame was minimized. 将内部框架InternalFrameListener
添加到内部框架,然后可以将public void internalFrameIconified(InternalFrameEvent arg0)
方法放入内部框架最小化时要执行的所有操作。 Here is this implemented in your code (without any AffineTransform
yet, just be basic concept): 这是在您的代码中实现的(尚无任何AffineTransform
,仅是基本概念):
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.swing.JComponent;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.event.InternalFrameEvent;
import javax.swing.event.InternalFrameListener;
public class AffineTransformTest {
private static TransformingCanvas canvas;
public static void main(String[] args) {
TransformingCanvas.initializePointList();
JFrame frame = new JFrame();
canvas = new TransformingCanvas(TransformingCanvas.POINT_LIST);
JDesktopPane desktop = new JDesktopPane();
TranslateHandler translator = new TranslateHandler();
canvas.addMouseListener(translator);
canvas.addMouseMotionListener(translator);
canvas.addMouseWheelListener(new ScaleHandler());
MyInternalFrame iFrame = new MyInternalFrame();
iFrame.setLayout(new BorderLayout());
iFrame.add(canvas, BorderLayout.CENTER);
iFrame.setVisible(true);
desktop.add(iFrame);
frame.setContentPane(desktop);
frame.setSize(750, 750);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setVisible(true);
}
private static class TransformingCanvas extends JComponent {
private double translateX;
private double translateY;
private double scale;
private final int PREF_W = 800; // Window width
private final int PREF_H = 800; // Window height
private static final Color INACTIVE_COLOR = Color.RED;
private static final Color ACTIVE_COLOR = Color.green;
private java.util.List<Point> points;
private java.util.List<Ellipse2D> ellipses = new ArrayList<>();
private Map<Ellipse2D, Color> ellipseColorMap = new HashMap<>();
public static java.util.List<Point> POINT_LIST = new ArrayList<>();
/*
* This loop will initialize POINT_LIST with the set of points for
* drawing the ellipses. The for each loop initializes points for the
* top row and the second for loop draws the right triangle.
*/
protected static void initializePointList() {
int ellipsePointsYCoordinate[] = { 140, 200, 260, 320, 380, 440,
500, 560, 620 };
int ellipsePointsXCoordinate[] = { 140, 200, 260, 320, 380, 440,
500, 560, 620, 680 };
int xx = 80;
for (int aXt : ellipsePointsXCoordinate) {
POINT_LIST.add(new Point(aXt, xx));
}
for (int i = 0; i < ellipsePointsYCoordinate.length; i++) {
for (int j = i; j < ellipsePointsYCoordinate.length; j++) {
POINT_LIST.add(new Point(ellipsePointsXCoordinate[i],
ellipsePointsYCoordinate[j]));
}
}
}
TransformingCanvas() {
translateX = 0;
translateY = 0;
scale = 1;
setOpaque(true);
setDoubleBuffered(true);
}
public TransformingCanvas(java.util.List<Point> points) {
this.points = points;
int OVAL_WIDTH = 30;
for (Point p : points) {
int x = p.x - OVAL_WIDTH / 2;
int y = p.y - OVAL_WIDTH / 2;
int w = OVAL_WIDTH;
int h = OVAL_WIDTH;
Ellipse2D ellipse = new Ellipse2D.Double(x, y, w, h);
ellipses.add(ellipse);
ellipseColorMap.put(ellipse, INACTIVE_COLOR);
}
}
@Override
public void paint(Graphics g) {
AffineTransform tx = new AffineTransform();
tx.translate(translateX, translateY);
tx.scale(scale, scale);
Graphics2D g2 = (Graphics2D) g;
g2.fillRect(0, 0, getWidth(), getHeight());
g2.setTransform(tx);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
for (Ellipse2D ellipse : ellipses) {
g2.setColor(ellipseColorMap.get(ellipse));
g2.fill(ellipse);
g2.setColor(Color.BLACK);
g2.setStroke(new BasicStroke(2));
g2.draw(ellipse);
}
/*
* Set the font characteristics, color, and draw the row labels.
*/
g.setFont(new Font("TimesRoman", Font.BOLD, 18));
g.setColor(Color.BLACK);
// NOTE to self: add label DrawStrings back
// Draws a 3DRect around the top row of ellipse2D objects
g2.setColor(Color.lightGray);
g2.draw3DRect(120, 60, 580, 40, true);
g2.draw3DRect(121, 61, 578, 38, true);
g2.draw3DRect(122, 62, 576, 36, true);
// super.paint(g);
}
}
private static class TranslateHandler implements MouseListener,
MouseMotionListener {
private int lastOffsetX;
private int lastOffsetY;
public void mousePressed(MouseEvent e) {
// capture starting point
lastOffsetX = e.getX();
lastOffsetY = e.getY();
}
public void mouseDragged(MouseEvent e) {
// new x and y are defined by current mouse location subtracted
// by previously processed mouse location
int newX = e.getX() - lastOffsetX;
int newY = e.getY() - lastOffsetY;
// increment last offset to last processed by drag event.
lastOffsetX += newX;
lastOffsetY += newY;
// update the canvas locations
canvas.translateX += newX;
canvas.translateY += newY;
// schedule a repaint.
canvas.repaint();
}
public void mouseClicked(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseMoved(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
}
private static class ScaleHandler implements MouseWheelListener {
public void mouseWheelMoved(MouseWheelEvent e) {
}
}
static class MyInternalFrame extends JInternalFrame implements
InternalFrameListener {
public MyInternalFrame() {
super("iFrame", true, // resizable
true, // closable
true, // maximizable
true);// iconifiable
setSize(300, 300);
addInternalFrameListener(this);
}
@Override
public void internalFrameActivated(InternalFrameEvent arg0) {
}
@Override
public void internalFrameClosed(InternalFrameEvent arg0) {
}
@Override
public void internalFrameClosing(InternalFrameEvent arg0) {
}
@Override
public void internalFrameDeactivated(InternalFrameEvent arg0) {
}
@Override
public void internalFrameDeiconified(InternalFrameEvent arg0) {
}
@Override
public void internalFrameIconified(InternalFrameEvent arg0) {
System.out.println("Minimized");
//What you want to do
}
@Override
public void internalFrameOpened(InternalFrameEvent arg0) {
}
}
}
If now you still can't achieve what you want, please explain further, as I don't really see the point of scaling Graphics that are not visible. 如果现在您仍然无法实现所需的功能,请进一步解释,因为我看不到扩展看不见的图形的要点。
Now that I understand what the real question was: You can add a ComponentListener
to your JInternalFrame
. 现在,我了解了真正的问题是:您可以将ComponentListener
添加到JInternalFrame
。 Then put inside the public void componentResized(ComponentEvent e) {
method everything that you want to change (probably the variables of the width and height of the Graphics
). 然后,将要更改的所有内容(可能是Graphics
的width和height的变量public void componentResized(ComponentEvent e) {
放入public void componentResized(ComponentEvent e) {
方法中。 Use the code above, just change the MyInternalFrame
class to this: 使用上面的代码,只需将MyInternalFrame
类更改为此:
static class MyInternalFrame extends JInternalFrame implements
ComponentListener {
public MyInternalFrame() {
super("iFrame", true, // resizable
true, // closable
true, // maximizable
true);// iconifiable
setSize(300, 300);
addComponentListener(this);
}
@Override
public void componentHidden(ComponentEvent e) {
}
@Override
public void componentMoved(ComponentEvent e) {
}
@Override
public void componentResized(ComponentEvent e) {
System.out.println("Resized");
System.out.println("Width: " + getWidth());
System.out.println("Height: " + getHeight());
System.out.println();
}
@Override
public void componentShown(ComponentEvent e) {
}
}
I'll give you an idea of how you could make it resize (change the componentResized
method to this): 我将为您提供一个如何调整其大小的想法(将componentResized
方法更改为此):
@Override
public void componentResized(ComponentEvent e) {
String str = "";
if (getWidth() < 1000) {
str = "0." + getWidth();
} else {
str = "1." + (getWidth()-1000);
System.out.println(getWidth()-1000);
}
double dou = Double.parseDouble(str);
canvas.scale = dou;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.