Java仿射变换在不同系统上的工作方式不同
我已经开始使用Java仿射变换在不同系统上的工作方式不同,java,affinetransform,Java,Affinetransform,我已经开始使用AffineTransform来旋转我正在用Graphics2D绘制的文本,我注意到它有时可以正常工作,而有时则不行,因为我刚刚意识到它在我的Windows 7 PC上总是像预期的那样工作,但在我的Windows 10笔记本电脑上却从来没有 我在两个系统上都使用Java15.0.1 下面是一个小测试用例,向您展示我的观点: import javax.swing.*; import java.awt.*; import java.awt.geom.AffineTransform;
AffineTransform
来旋转我正在用Graphics2D
绘制的文本,我注意到它有时可以正常工作,而有时则不行,因为我刚刚意识到它在我的Windows 7 PC上总是像预期的那样工作,但在我的Windows 10笔记本电脑上却从来没有
我在两个系统上都使用Java15.0.1
下面是一个小测试用例,向您展示我的观点:
import javax.swing.*;
import java.awt.*;
import java.awt.geom.AffineTransform;
public class AffineTransformTest extends JPanel {
private static final int SIZE = 40;
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
int centerX = getWidth()/2;
int centerY = getHeight()/2;
g2.setColor(Color.BLACK);
g2.drawRect(centerX - SIZE/2, centerY - SIZE/2, SIZE, SIZE);
AffineTransform at = g2.getTransform();
at.setToRotation(Math.toRadians(45),centerX, centerY);
g2.setTransform(at);
g2.setColor(Color.RED);
g2.drawRect(centerX - SIZE/2, centerY - SIZE/2, SIZE, SIZE);
}
public static void main(String[] args) {
JFrame frame = new JFrame();
AffineTransformTest test = new AffineTransformTest();
frame.setContentPane(test);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300,300);
frame.setVisible(true);
}
}
黑色矩形是一个规则的中心,位于“代码> JPANDOCT/<代码>的中间。 红色矩形在旋转45°后绘制,应该与黑色矩形共享同一中心(如第一张图片所示)
然而,我的笔记本电脑产生的结果显示在第二张图片上 |这怎么可能呢?这可能是因为您违反了Javadoc声明的paintComponent()方法的约定 如果在子类中重写此项,则不应将其设为永久 对传入图形的更改。例如,您不应该更改 剪切矩形或修改变换。如果你需要做这些 操作您可能会发现从 传入图形并对其进行操作 因此,可能是Windows 7和Windows 10本机UI实现之间的细微差异导致了一个中断而另一个未中断 要查看这是否确实是原因,请尝试更改行
Graphics2D g2=(Graphics2D)g代码>到图形2d g2=(图形2d)g.创建()代码>将克隆图形对象并保持原始对象不变
编辑以澄清正确答案:
该问题是由at.setToRotation
调用在绘制黑色正方形之后和绘制旋转的红色正方形之前清除图形上下文上的默认缩放变换引起的。建议的解决方案是调用rotate(θ,x,y)
直接在Graphics2D
对象上的方法形式,该对象保留现有的比例变换。我最初认为我可能希望获得原始仿射变换,并将其放在一边,然后在图形上设置我自己的仿射变换,以便我可以将其放回以还原它。可悲的是,这没有帮助。我将尝试你的方法并让你知道。因此,使用(Graphics2D)g.create()创建副本代码>但没有更改。看起来完全一样。你的Win10笔记本电脑是否有可能显示高DPI?如果是这样的话,则可能是at.setToRotation
调用正在清除图形上下文上的初始缩放变换,从而导致这种奇怪的行为。在任何情况下,最好的做法是执行g2.旋转(Math.toRadians(45),centerX,centerY)
,而不是直接操纵仿射变换。您似乎完全正确!我确实将我的Windows10UI扩展到125%,我将其设置回100%,看看这是否真的是原因,也确实是原因。我也没有意识到Graphics2D
包含的旋转方法。这就是我为什么那样做的原因。我确实想知道最初的方法是否不起作用,或者是一个bug,但无论如何,我保留了(Graphics2D)g.create()编码>零件并使用图形2d.旋转
方法,它最终可以正常工作!非常感谢你!