I have a Canvas class, which is an extension of JPanel. I need to draw multiple custom shapes on it and be able to resize them. I finished drawing all the elements, I did the logic for selecting those elements and drawing a section rectangle, but I can't resize them. I tried using affine transformation and the scale() method, but when I scale using those methods, it scales all elements on the canvas, not just one. Any idea how could I make it scale only one element, without scaling others?
Assuming your painting your elements within the paintComponent method...
Create a new copy of the Graphics context...
Graphics2D g2d = (Graphics2D)g.create();
Create and apply you affine transformation...
AffineTransform at = anew AffineTransform();
at.translate(...);
at.scale(...);
g2d.setTransform(at);
Paint your element(s) and dispose of the Graphics context you have created...
//... Paint...
g2d.dispose();
Repeat as required.
The other method might be to get the current transformation and re-apply it when your done...
AffineTransform currenrAT = g2d.getTransform();
// Apply new transform and paint...
g2d.setTransform(currentAT);
Related
I looked everywhere to see with anyone had the same problem than me but it seems I'm the only one getting this error.
So I'm in Java with Swing. I have a class Player that draws an image of the player. However, each time I tried to use setTransform to rotate my image, the second instance of player is scaled down by two.
Here is my code for the draw method:
AffineTransform transform = new AffineTransform();
transform.rotate(this.getOrientationRadians(), getX()+getWidth()/2,getY()+getHeight()/2);
g.setTransform(transform);
g.drawImage(image, (int)(getX()), (int)(getY()), null);
g.setTransform(new AffineTransform());
By overwriting the transform of the Graphics object you are also overwriting the scaling imposed by your system scale (which I suppose is set to 200%).
Either restrict to using Graphics2D::rotate or pass the transform the drawImage call.
AffineTransform transform = new AffineTransform();
transform.translate(getX(), getY());
transform.rotate(getOrientationRadians());
g.setTransform(transform);
g.drawImage(image, transform, null);
I want to rotate the text present on my JComponent to vertical, JComponent also contains border painted in paintComponent method, I don't want to rotate that border, only text.
I already used graphics2D rotate function, but it rotate component border as well, which fails when my component is rectangle.
Please suggest me any approch to rotate only text.
This is currently my JComponent :
And what I want :
Actually it's not duplicate. I already used below code:
Graphics2D g2 = (Graphics2D) g;
g2.rotate(Math.PI / 4, bi.getWidth() / 2, bi.getHeight() / 2);
but problem is that, it also rotate border, I don't want that.
All the solutions given are not working, it rotate the border as well. I don't want to rotate the border, only text.
This is what I get after rotate with some angle:
Remember that the Graphics object has a lot of state in it. This includes the current transformation. Your current code modifies the state and does not restore it to the original situation.
After drawing your image, you should "undo" the rotation. This can be done either by rotating in the other the direction or by creating a new graphics object (g2.create()) specifically to draw the rotated content. If you do the latter, make sure to dispose() the temporary graphics object you created.
I'm making a game where you start by drawing your map. At the moment it works by having an Area instance variable and then when the player clicks/drags the mouse it adds Ellipse2Ds to it. Here's what I mean:
Area land = new Area();
And then in the MouseDragged method
Point2D mouse = e.getPoint();
Ellipse2D ter = new Ellipse2D.Double(mouse.getX() - drawRad, mouse.getY() - drawRad, drawRad*2, drawRad*2);
land.add(new Area(ter));
And then basically the same except land.subtract(new Area(ter)) for erasing.
My problem with this is that after doing a lot of drawing it becomes very slow to draw the Area. the other problem is that I would like to be able to easily get the outline of the drawing, and I haven't found a good way of doing that using Areas. Using area.getPathIterator is not nearly accurate enough.
So I'm wondering what other ways of saving drawings are? I can't just have an array of Ellipses because then erasing wouldn't work.
Thanks!
If you are drawing the same thing over and over it may be worth while to draw it to an image once or load it from a file at start up and then just paint the image rather than painting all the individual shapes.
To load from a file, put your picture file in the same directory as your .java file and load:
BufferedImage img = ImageIO.read(this.getClass().getResource("picture.png"));
To draw on the image once:
BufferedImage img = new BufferedImage(width,height, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D g = img.createGraphics();
In your paintComponent method you draw the image somewhere.
g.drawImage(img, 0, 0, this);
If you have something moving over a background, instead of adding and subtracting the moving item. Just draw the background and then draw the thing that moves, drawing the background will effectively erase the old position with less computation.
In a Java Swing panel I draw an image with arbitrary transfomation e.g.:
public void paintComponent(Graphics g){
AffineTransform transform = AffineTransform.getTranslateInstance(x, y);
AffineTransform rotateInstance AffineTransform.getRotateInstance(rotX, rotY);
transform.concatenate(rotateInstance);
g.setTransform(transform);
g.drawImage(image, 0, 0 , null);
}
What is the best way to detect mouse over on such an image?
Even better: the best way to detect mouse over only on non-transparent pixels?
Construct a Shape that encloses the image, and use the AffineTransform method createTransformedShape() to rotate the Shape along with the image. The Shape method contains() will allow for position testing in Component relative coordinates. Complete examples are seen here and here. Two approaches to inverse coordinate transformation are cited here.
is there a possibility to draw a JPanel on a specific location op a Graphics (or Graphics2D) object?
I override the paint method of my canvas, and call panel.paint(g) in there, but it does not work the way I woul hope.
#Override
public void paint(Graphics g){
Dimension size = panel.getPreferredSize();
panel.setBounds(pos.x, pos.y, size.width, size.height);
panel.paint(g);
}
the size object is correctly defined as I would wish, so that's not the problem. Also, the pos contains a correct x and y on the screen.
You should probably be using paintComponent instead of paint, since the latter is the AWT method, and the former is the Swing method.
One nice thing about Swing's paintComponent is that the Graphics passed is actually always going to be a Graphics2D, so you can:
Graphics2D g = (Graphics2D)lg;
Now you can use the getTransform to save the old transform, then modify the transform of the Graphics2D using either setTranform or the scale, translate and rotate methods. Don't forget to restore the old transform, or you'll likely fudge the next thing being drawn by that context.
I'll throw in that, depending on the circumstance, drawing to a BufferedImage might be appropriate. You can get a Graphics context using BufferedImage.getGraphics(). Then you can draw the BufferedImage's context by whatever means suit you.