Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
130 views
in Technique[技术] by (71.8m points)

Java AffineTransform working differently on different systems

I have started using AffineTransform to rotate text I'm drawing with Graphics2D and I noticed it would sometimes work fine and other times it wouldn't when I just realized that it works always as expected on my Windows 7 PC but never on my Windows 10 laptop.

I use Java 15.0.1 on both systems.

Here is a small test case to show you my point:

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);
    }
}

The black rectangle is a regular one centered in the middle of the JPanel. The red rectangle is drawn after a 45° rotation and is supposed to share the same center as the black one (as shown on the first picture).

My laptop however produces the result shown on the second picture.

Expected result - Windows 7 | Incorrect result - Windows 10

How can this be?

question from:https://stackoverflow.com/questions/65829170/java-affinetransform-working-differently-on-different-systems

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

This is likely because you are violating the contract of the paintComponent() method, where the Javadoc states

If you override this in a subclass you should not make permanent changes to the passed in Graphics. For example, you should not alter the clip Rectangle or modify the transform. If you need to do these operations you may find it easier to create a new Graphics from the passed in Graphics and manipulate it.

So maybe subtle differences between the Windows 7 and Windows 10 native implementations of the UI is why one breaks and the other doesn't.

To see if this is indeed the cause, try changing the line Graphics2D g2 = (Graphics2D)g; to Graphics2D g2 = (Graphics2D)g.create(); which will make a clone of the Graphics object and leave the original unchanged.

Edit to clarify the correct answer: The issue was caused by the at.setToRotation call clearing the default scaling transform on the graphics context after drawing the black square and before drawing the rotated red square. The recommended solution is to call the rotate(theta,x,y) form of the method directly on the Graphics2D object which preserves the existing scale transform.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...