3

Hello I am new to affineTransform in java. I want to use it to shear some GUI I have to use later. For now I just wanted to test a sample code but i cannot explain its output. Here is the code

    package main;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.FlowLayout;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.geom.AffineTransform;

    import javax.swing.BorderFactory;
    import javax.swing.JFrame;
    import javax.swing.JPanel;

    public class MainClass{
    public static void main(String[] args) {
    JFrame jf = new JFrame("Demo");

    jf.getContentPane().add(new MyCanvas());

    jf.setSize(600, 600);
    jf.setVisible(true);
  }
}

    class Left extends JPanel {

    Left(){
        setPreferredSize(new Dimension(450,450));
        setBorder(BorderFactory.createLineBorder(Color.green));
        setBackground(Color.gray);

    }


      public void paintComponent(Graphics g) {

            super.paintComponent(g);

            Graphics2D g2 = (Graphics2D) g;

            AffineTransform at = new AffineTransform();

            g2.setTransform(at);

            g2.drawRect(getWidth()/2 - 10, getHeight()/2 - 10, 20, 20);

          }
}

    class MyCanvas extends JPanel {

    MyCanvas()
    {
        setBorder(BorderFactory.createLineBorder(Color.red));
        setLayout(new FlowLayout(FlowLayout.CENTER));
        add(new Left());
    }


}

The rectangle I want to draw in the Left class show appear in the center right?? But its coming shifted to left.. It seems its taking its coordinates with relative to the outer frame. If I remove the g2.setTransform(at); it comes normal.. Can you explain me why??

mre
  • 43,520
  • 33
  • 120
  • 170
coder
  • 823
  • 2
  • 10
  • 17

4 Answers4

7

The setTransform method is intended only for restoring the original Graphics2D transform after rendering. That being said, you should never apply a new coordinate transform on top of an existing transform because the Graphics2D might already have a transform that is needed for other purposes, such as rendering Swing components. Your code exemplifies this point. To add a coordinate transform, use the transform, rotate, scale, or shear methods.

mre
  • 43,520
  • 33
  • 120
  • 170
  • 1
    you must have big/large FanClub, nothing else (put all your posts together) +1 – mKorbel Jul 15 '11 at 16:11
  • if someone down-vote any post without wrotten valuable reason(s), then why elaborate about that, just her/him disagreement without efect, nothing else, why asking for that, if s/he wants that then probably would be wrote why :-) – mKorbel Jul 15 '11 at 16:23
  • you must have really hot head, why flames, quite ignore that, not true your status, professional community == lots of people are there for fun, like my person :-) – mKorbel Jul 15 '11 at 16:31
  • 2
    @little: I'm neither the down-voter nor a moderator; I up-voted ~11 hours ago. It looks like all answers here were systematically down-voted, as well as ~30 of yours. You can [audit](http://meta.stackexchange.com/questions/43004/how-do-i-audit-my-reputation) your account to see more. If the automatic [fraud detection mechanism](http://meta.stackexchange.com/questions/19920/how-does-the-so-voter-fraud-detection-mechanism-work) doesn't catch it, you can flag it for moderator attention. I've been hit both ways. – trashgod Jul 16 '11 at 02:11
3

You are probubly drawing some lightweight component. That means it does not have its own coordinate system. So it use its closest heavy weight parrent's coord. system.

Therefore you should combine transformation you want to do with original transformation (by multiplying them.

And after you are done drawing, you (maybe) should restore original transformation.

Alpedar
  • 1,314
  • 1
  • 8
  • 12
  • I don't see where there's a mixing of lightweight and heavyweight components. What are you talking about? – mre Jul 15 '11 at 12:34
  • 1
    To draw anything, there must be HW component. And lot of things in swing are LW. JFrame is the HW one, Panel is LW, and is centered, so its shifted to the side and that is done by affine transformation and cliping. – Alpedar Jul 18 '11 at 08:18
2

Expanding on @littel's answer, you can compare the current transform to the identity as the frame is resized using the example below. Note that only the translational components vary: dx = 75.0 is half the difference between the width of MyCanvas and Left, while dy includes the vertical offset of Left and the size of the green border.

Identity: AffineTransform[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]
Identity: AffineTransform[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]
Current: AffineTransform[[1.0, 0.0, 75.0], [0.0, 1.0, 201.0]]
Current: AffineTransform[[1.0, 0.0, 75.0], [0.0, 1.0, 1.0]]

Demo image

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.geom.AffineTransform;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class MainClass {

    public static void main(String[] args) {
        JFrame jf = new JFrame("Demo");
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.setLayout(new GridLayout(0, 1));
        jf.add(new MyCanvas());
        jf.add(new MyCanvas());
        jf.pack();
        jf.setLocationRelativeTo(null);
        jf.setVisible(true);
    }
}

class MyCanvas extends JPanel {

    MyCanvas() {
        setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
        setPreferredSize(new Dimension(600, 200));
        setBorder(BorderFactory.createLineBorder(Color.red));
        add(new Left(), BorderLayout.CENTER);
    }
}

class Left extends JPanel {

    Left() {
        setPreferredSize(new Dimension(450, 100));
        setBorder(BorderFactory.createLineBorder(Color.green));
        setBackground(Color.gray);
        System.out.println("Identity: " + new AffineTransform());
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        System.out.println("Current: " + g2.getTransform());
        g2.drawRect(getWidth() / 2 - 10, getHeight() / 2 - 10, 20, 20);
    }
}
Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
-3

I know where is you problem, you draw on same graphics as parent. "super.paintComponent(g);"

you should try something like super.repaint();

Zemzela
  • 3,060
  • 6
  • 23
  • 32
  • 3
    -1, invoking `repaint()` within the `paintComponent()` method is a no-no. – mre Jul 15 '11 at 12:44
  • @little bunny foo foo before gives -1, give constructive argument. Very rude from you. – Zemzela Jul 15 '11 at 13:07
  • Well, it's very rude for you to misinform others. :) – mre Jul 15 '11 at 13:08
  • explain why is no-no for invoking repaint(). No-no is no argument, thats why is rude. – Zemzela Jul 15 '11 at 13:29
  • 1
    Simple - because you'll end up invoking `paintComponent()` continuously until the program terminates. For future reference, refrain from claiming that you "know" where the problem is when you clearly don't. – mre Jul 15 '11 at 13:42
  • then try and run the code with super.repaint(), then tell me if continuously invokes. actually the problem is when he paint on parents graphics, and that is as I say. – Zemzela Jul 15 '11 at 16:02
  • 1
    I did, and it does. By the way, are you going through all my answers/questions and down-voting them? – mre Jul 15 '11 at 16:09
  • @littlebunnyfoofoo let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/1515/discussion-between-zemzela-and-sthupahsmaht) – Zemzela Jul 15 '11 at 16:13
  • 1
    infinite loop - enough said – BAR Mar 28 '13 at 15:57