AWT - rotate the entire Swing panel - java

I'm experiencing a problem with AWT in rotating the graphics in a panel by 90 degrees.
I can rotate the graphics in a panel by casting to Graphics2D and applying a transform.
The problem with this is that if the panel area is rectangular then part of the graphics becomes hidden. I can't seem to set clip bounds to the whole area.
If, for example, the window is short and wide then the clip region becomes narrow and tall. If the window is narrow and tall the clip region becomes short and wide. I don't know how to override this behavior.
Is there a better way of doing this or a way to work around the problem?
EDIT SOLVED:- It turns out that overriding behavior of getWidth() and getHeight() is a bad idea lol

As shown here, override getPreferredSize() on the enclosing panel to return a Dimension that can accommodate your desired view, e.g. Math.max(width, length). As shown here,
Translate the image to the origin.
Rotate the image.
Translate the image back to the center of the panel.

Related

Adding rendering offset to Frame

The scenario here is as so: I am using a Frame object to do some lower-ish level rendering with AWT (no Swing). The only issue is, Frames, when rendering directly to them, do not account for their borders. So, as we all likely know, rendering a Rectangle at (0,0) does not look like it is doing the right thing. This is because (0,0) is the literal top-left of the Frame.
So the problem is, instead of adding in the Frame insets for everything to be rendered on-screen like so:
//This is within the rendering method in the Frame subclass. A buffer strategy is already created
Graphics2D g = (Graphics2D)bufferStrategy.getDrawGraphics();
g.clearRect(0, 0, getWidth(), getHeight());
g.setColor(Color.WHITE);
Insets insets = this.getInsets();
g.drawString("FPS: " + getFPS(), 100 + insets.left, 100 + insets.top); //<-- Ugh.
g.dispose();
I would like to be able to simply add an offset of sorts to the underlying graphics of the Frame. Is this possible? To be clear, it would be nice to have some functionality like this:
g.setDrawingOrigin(x, y);
With this sort of method, I could get away with murder. I don't know why there wouldn't be one buried somewhere...
NOTE: It is a Frame and not a JFrame, so we lack a content pane to reference. Another thing, it would be nice to avoid adding any other component to the Frame. I am trying to keep this as lightweight as possible (hence, the Frame instead of JFrame. Okay, there isn't much of a difference, but let me have my fun :D).
The method you are looking for is Graphic's translate(int, int).
So you would call,
g.translate(insets.left, insets.top);
One other approach is that instead of drawing to the Frame directly, you can add another component which fits and uses all of the Frame's space, and then do all the drawing in that subcomponent's paint method where x and y are where you expect.
Directly from the JavaDocs...
The size of the frame includes any area designated for the border. The dimensions of the border area may be obtained using the getInsets method, however, since these dimensions are platform-dependent, a valid insets value cannot be obtained until the frame is made displayable by either calling pack or show. Since the border area is included in the overall size of the frame, the border effectively obscures a portion of the frame, constraining the area available for rendering and/or displaying subcomponents to the rectangle which has an upper-left corner location of (insets.left, insets.top), and has a size of width - (insets.left + insets.right) by height - (insets.top + insets.bottom).

Java - Scaling a canvas about a particular point

I am more or less finished a very simple planetary gravity simulator using Newtonian physics. It can transform and scale the planets for pan and zoom. This works fine, mouse input and everything. The problem I have is more aesthetic than anything else. Since the origin of the canvas is at the top left corner of the window (within a JPanel, within a JFrame), everything scales about that point. I was wondering is there any way to either set the origin to the center of the screen, or to scale about a particular point? (Even though AffineTransform.scale() only has one constructor, with scaleX and scaleY as the args). I have tried setting the bounds of the canvas as negative numbers as such:
canvas.setBounds(-width/2, -height/2, width/2, height/2);
(Width and height are the screen size).
This obviously doesn't work as negative numbers are outside the co-ords of the panel.
So does anyone know anyway of accomplishing this? Either setting the centre of the screen as the origin or scaling about a particular point rather than the origin?
The trick here is to concatenate instances of AffineTransform.
Move the entire rendering so the center is at the origin.
Scale the rendering.
Move the center of the rendering (now at the origin) back to the center of the view.

Fading a portion of Graphics in Java Swing

I am trying to implement the fade in/fade out animation in swing.
I am using a JPanel which does not have any components in it. It is completely drawn by paintComponent() method.
Now in one of the portion of this JPanel, I want to implement the fade in/fade-out animation. When I tried using AlphaComposite, the animation is being triggered for whole JPanel.
Can I limit this animation in a small clipped region in that panel?
Graphics2D g2d = (Graphics2D) g;
g2d.setComposite(AlphaComposite.getInstance(
AlphaComposite.XOR, alpha));
Have you tried using an Graphics object (like rectangle, circle etc..) for your fade in/out? That way it won't be triggered for the complete panel.
Good luck!
Perhaps, but that may be more difficult to achieve than what it's worth. Create a JComponent of the size you want to animate (or fade), add it to your JPanel, and have repaint() called on your smaller component during animation instead of the larger JPanel.
You can use setClip() before painting to restrict the fading area.
Suppose you want a small fading rectangle. Using Area class create 2 Shapes. Intersection of original clip and fading rect and subtraction (subtract the fading rectangle from the original clip).
Call super.paintComponent() twice with 2 different clips. For the second paint you can set your alpha filter.

JComponent JPanel Zoom, pan and Coordinates Question

I have a JPanel with an vector image that the user can zoom and pan on. Overlaying this image is a (transparent) JComponent, which I allow the user to annotate the underlying image. This works great at full scale, but If I zoom in, using AffineTransform, the overlaying coordinates are affected also. So, If a user draws a box on the image the box is scaled also.
Any suggestions on how to decouple this behaviour? So that the JComponent is not affected by the JPanel's AffineTransform?
Typically, you need both a forward and inverse transform to translate between the two co-ordinate systems. In this example, the scaling equations are explicit; in this alternate approach, a second AffineTransform is used.

can we zoom in zoom out the drawing we draw on the Canvas?

We have an old (more than 10yrs old) Java Swing applicatin which draws lots of circles and connections (lines) between those circles on a JCanvas (a subclass of JComponent) based on lab data.
Because the data becames bigger and bigger, we cannot display the entire drawing now. We have put the JCavans into a JScrollPane but it is not convenience to scroll the drawing.
Can we add zoom in zoom out for it? if yes, how? I know we can zoom image but the drawing on Canvas is an image?
thanks,
EDIT:
we draw those circles and line with Graphics within paintComponent(Graphics g) method.
You could apply a scaling Transform to the Graphics2D object passed to the paintComponent method. You can learn how to use it in the Java 2D programming trail.
Without knowing anything about your application it's hard to provide useful advice (adding a code snippet or better yet a cutdown example app would be helpful to show how things are being drawn), but I'll give it a shot:
Why don't you multiply the x,y and width,height values by a scaling factor before you draw each circle/line? I assume that somewhere your canvas is using a Graphics object to draw each shape?

Categories