سؤال

I need to place some geometrical primitives and texts, using java.awt.Graphics2d. If i scale them i expect that the relative position of elements to each other is scale-independent. Unfortunately if i just use Graphics2D.scale(...) to draw some Objects with Graphics2D.drawRectangle(...) and Graphics2D.drawString(...)the relative position changes. It's good to illustrate with this image:

enter image description here

So this is code, that produses this image:

public class Main {
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setTitle("Title");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.add(new JPanel() {
            {
                setPreferredSize(new Dimension(1024, 300));
            }

            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2 = (Graphics2D) g;
                g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

                for(int i = 1; i < 5; i++) {
                    doDraw(g2, i, i*10);
                }
            }

            void doDraw(Graphics2D g2, double scale, int yOffset) {
                String txt = "A-->                                                B";

                AffineTransform at = g2.getTransform();

                g2.scale(scale, scale);
                g2.setColor(Color.DARK_GRAY);
                g2.drawRect(10, 10 + yOffset, 234, 20);
                g2.drawString(txt, 14, 24 + yOffset);

                g2.setColor(Color.red);
                g2.drawOval(228, 12 + yOffset, 14, 14);

                g2.setTransform(at);
            }
        });

        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

As you can see i the positions of elements is constant. The only thing that is changed is scale. At 100% the red circle is exactly on B-letter. But at 300% and more it's completly wrong. Am i doing something wrong or is it a bug in java? Is there any workaround for that issue?

The thing i want actually to achieve is, that at any scale the red circle is always painted around the letter "B".

UPD: I assume the reason why it happens, is how java renders scaled font. That's not just font, that is scaled like geometrical opereations, but for any scale java takes an apropriate dot size font. So Arial 8 at 75% is rendered just as Arial 6, not Arial 8 scaled down on 3/4. Otherweise scaled text would look auwful. But may be i am wrong with that.

UPD 2: tryed SwingUtilities2.drawText() - no effect.

Background: Actually i am making a sort of vector editing program. So i have objects in document, that have X, Y-coordiantes. So i just want to place them somehow in document. The problem is that by changing zoom, the objects "jumps" at they relative positions to each other. So if i want to make some text like CHECKED and make letter C being in a box/circle, it depends on scale.

هل كانت مفيدة؟

المحلول

Try to set also RenderingHints.KEY_FRACTIONALMETRICS to ON for the Graphics instance

نصائح أخرى

You should work with g.getFontMetrics(font) in order to compute the right size for the font.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top