【发布时间】:2018-08-15 20:21:10
【问题描述】:
在使用 Java Swing 围绕缩放操作拆分翻译操作时,我发现了一些奇怪的事情。也许我在做一些愚蠢的事情,但我不确定在哪里。
在第一个版本中,我将图像居中、缩放,然后将其转换到所需位置。 在第二个版本中,我直接缩放图像,然后转换到所需的位置,以补偿具有非居中图像。 这两种解决方案应该是等价的。在考虑围绕一个点的旋转和另一个点的运动时,这一点也很重要。我也有这样做的代码...但是为什么这不起作用?
这是代码的两个版本。他们应该做完全相同的事情,但事实并非如此。以下是截图:
首先产生:screenshot1
二次生产:screenshot2
我认为draw1中围绕缩放操作的两个平移操作应该等同于draw2中的缩放平移操作。
有什么建议吗?
MCVE:
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.*;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.net.URL;
public class Asteroid extends JComponent implements ActionListener {
public static final Dimension FRAME_SIZE = new Dimension(640, 480);
public double x = 200;
public double y = 200;
public int radius = 40;
private AffineTransform bgTransfo;
private final BufferedImage im2;
private JCheckBox draw1Check = new JCheckBox("Draw 1", true);
Asteroid() {
BufferedImage img = null;
try {
img = ImageIO.read(new URL("https://i.stack.imgur.com/CWJdo.png"));
} catch (Exception e) {
e.printStackTrace();
}
im2 = img;
initUI();
}
private final void initUI() {
draw1Check.addActionListener(this);
JFrame frame = new JFrame("FrameDemo");
frame.add(BorderLayout.CENTER, this);
frame.add(BorderLayout.PAGE_START, draw1Check);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
Asteroid asteroid = new Asteroid();
}
@Override
public Dimension getPreferredSize() {
return FRAME_SIZE;
}
@Override
public void paintComponent(Graphics g0) {
Graphics2D g = (Graphics2D) g0;
g.setColor(Color.white);
g.fillRect(0, 0, 640, 480);
if (draw1Check.isSelected()) {
draw1(g);
} else {
draw2(g);
}
}
public void draw1(Graphics2D g) {//Draw method - draws asteroid
double imWidth = im2.getWidth();
double imHeight = im2.getHeight();
double stretchx = (2.0 * radius) / imWidth;
double stretchy = (2.0 * radius) / imHeight;
bgTransfo = new AffineTransform();
//centering
bgTransfo.translate(-imWidth / 2.0, -imHeight / 2.0);
//scaling
bgTransfo.scale(stretchx, stretchy);
//translation
bgTransfo.translate(x / stretchx, y / stretchy);
//draw correct position
g.setColor(Color.CYAN);
g.fillOval((int) (x - radius), (int) (y - radius), (int) (2 * radius), (int) (2 * radius));
//draw sprite
g.drawImage(im2, bgTransfo, this);
}
public void draw2(Graphics2D g) {//Draw method - draws asteroid
double imWidth = im2.getWidth();
double imHeight = im2.getHeight();
double stretchx = (2.0 * radius) / imWidth;
double stretchy = (2.0 * radius) / imHeight;
bgTransfo = new AffineTransform();
//scale
bgTransfo.scale(stretchx, stretchy);
//translate and center
bgTransfo.translate((x - radius) / stretchx, (y - radius) / stretchy);
//draw correct position
g.setColor(Color.CYAN);
g.fillOval((int) (x - radius), (int) (y - radius), (int) (2 * radius), (int) (2 * radius));
//draw sprite
g.drawImage(im2, bgTransfo, this);
}
@Override
public void actionPerformed(ActionEvent e) {
repaint();
}
}
【问题讨论】:
-
因为
position是每个圆的中心,而fillOval和drawImage要求位置是左上角。 -
如需尽快获得更好的帮助,请发帖minimal reproducible example 或Short, Self Contained, Correct Example。
-
@meowgoesthedog 是的,我知道我重新对齐了图像(例如,我在两个版本中减去半径.. 在第一个版本中使用第一个翻译,在第二个版本中使用 uniq 翻译..)跨度>
-
是的,但是在
draw1中调用bgTransfo.translate时,您传递了position而不是position - radius。这是关键线。 -
Dmitri,我认为这里的基本问题是:您了解
AffineTransform的作用以及scale+translate的确切组合吗?我认为如果您暂时删除scale(也不要除以stretchx/stretchy),问题就会变得非常明显。然后,当您申请scale时,考虑到stretchx/stretchy在translate内的划分,它显然对这个问题没有任何作用。
标签: java swing math graphics java-2d