How to rescale painted contents of JPanel - java

I have a window which contains upper JPanel where figures are painted and the lower JPanel where figures are listed in the JList the list looks like:
[minature][figure.toString()]
The minature is JPanel of a size 10x10. I would like it to contain minature of drawn figure in the upper Panel. By it I mean.
class minaturePanel{
Figure f;....
public void paint(Graphics g){
g.drawFullSizeFigure(f);
g.rescaleWholeInsidesOfThePanel();
}
}

This example paints into a BufferedImage and uses AffineTransformOp to do the scaling.
You may also want to look at JScrollNavigator, examined here. It lets you navigate on a thumbnail image of your entire component, seen at full size in an adjacent scroll pane.

It seems you want to draw your full figure to an image, return the image, and then rescale the image then draw the image on the panel which will be the right size as the panel now. Actually you can rescale the image while drawing it.

If the Figure has no capacity to scale it self. You can use a AffineTransformation to scale the Graphics context your self. Just don't forget to restore the previous transformation...
Check out Transforming Shapes, Text, and Images for more details.

Related

Performance-minded way to draw a scaled image in a JPanel

I have a Java Application that includes functionality to load in photos to show a user that they choose, but I want the width of each photo to be a max of 200 pixels.
My current solution is to use a class that subclasses JPanel, and in its constructor, I load the image and calculate the correct size.
I override paintComponent(Graphics g) and draw the image there using:
super.paintComponent(g);
g.drawImage(image.getScaledInstance(width, height, Image.SCALE_FAST), 0, 0, this);
However, this resizes the image once every frame, since paintComponent is called every frame, and I’d prefer to only have to resize the image once and draw that.
Is there a way to achieve better performance, doing what I need it to do?

Image only paints within original bounds

I want to animate several jpgs in a JFrame, I'll show you some extracts:
My class constructor that extends JFrame
super(title);
setLayout(null);
setResizable(false);
setSize(Settings.windowWidth, Settings.windowHeight);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
My class constructor that extends JPanel
i = new ImageIcon(image).getImage();
setSize(i.getWidth(this),i.getHeight(this));
setBounds(x, y, i.getWidth(this), i.getHeight(this));
The overwritten method
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(i, getX(), getY(), null);
}
Yes, I know null layout isn't preferrable, but unless you have a better idea for absolute positioning I'll stick with it for now.
Above code does paint the image, starting at (x,y), but not completely.
For 50 and 100 it shows this:
Which is pretty much: It only paints the image within a 256x256 box (image dimensions) from 0,0, no matter where it has been relocated to.
Any advice, help, solutions, suggestions?
If you need more code, ask me, just don't feel like putting everything around it in here, too ;)
There is no need for custom painting:
Add the ImageIcon to a JLabel and add the JLabel to a JPanel
Change the location of the label on the panel when you want to animate it.
Or, if you do custom painting then there is no need for a null layout.
You override the getPreferredSize() method of the JPanel and add your panel to the frame.
Then in the paintComponent() method you can paint the image where every you want withing the bounds of the preferred size that you set.
My gut feeling is you don't understand how component painting actually works...
First, you do this...
i = new ImageIcon(image).getImage();
setSize(i.getWidth(this),i.getHeight(this));
setBounds(x, y, i.getWidth(this), i.getHeight(this));
Then you do this...
g.drawImage(i, getX(), getY(), null);
which seems to be painting the image at a offset position from the components origin, but since the component is sized to match the size of the image, the image is cropped at the component boundaries.
When a component is painted, the Graphics context's origin is set to the components location, meaning that 0x0 is now the components top/left corner.
You can test this by using setBorder(new LineBorder(Color.RED)), which will show you the physical bounds of the component
In your case, something like
g.drawImage(i, 0, 0, this);
In your case, you should be moving the component not the image.
Personally, I'd add the JPanel to the JFrame using a BorderLayout, then you can simply move the image anywhere within the context of the component itself. Remember to override getPreferredSize to return an appropriate size for your purposes so the frame can be packed around it more effectively.
It's tricky to do animation with components (not impossible, there's just a lot to take into account), generally it's just easier to paint directly to a canvas like a JPanel, but that's me
See Painting in AWT and Swing and Performing Custom Painting for more details about how painting works

Viewing large image size using BufferedImage in Java

I currently have an image that I load into program as a BufferedImage. This BufferedImage is put inside a JPanel class which has a fixed size.
Now the problem I am facing is that how can I pan this large BufferedImage inside this fixed size JPanel.
The JPanel dimension is definitely smaller than the image.
Thanks!
First, attach some scroll bars to the JPanel (south and east, using a BorderLayout) that will be visible only if the image is too large and/or high. Attach another JPanel in the remaining space (center). In that inner JPanel, you would override the paintComponent method and would draw the portion of your BufferedImage into the JPanel. Use the scroll bars' offset to offset your image, and the inner JPanel for the width and height to draw (the viewport).
Note: your scroll bars will invoke the repaint method of your inner JPanel whenever their value change.
The paintComponent will be called by the system automatically (or manually) whenever the image needs to be redrawn. Doing this, you will be able to customize the view you give your image (if such feature is needed); rotation, scaling, pixel manipulation, custom overlays etc.
You can also attach some MouseMotionListener to the inner JPanel and modify the scroll bars' offset according the mouse movements (modifying the scroll bars will automatically trigger the repaint on the image) for mouse interaction with your component. Just a thought.

How to add multiple layers onto JPanel

I need some help with Java Swing components and its capabilities. I need to add a JPanel to a JFrame and paint an Ellipse2D on it. Onto the Ellipse2D I want to add another element, in my case it is a picture (right now I use an ImageIcon, maybe wrong). How can I achieve adding the Ellipse2D and the picture on the panel as shown in the image I attached?
The reason why I need the images separated is, because I need to change the filling color of the ellipse sometimes.
Thanks for any help.
What you need is to create a custom JPanel implementation and override paintComponent method.
Inside it, you just do:
public void paintComponent(Graphics g) {
super.paintComponent(g);
// Draw ellipse here
// Draw your image here. It will be drawn on top of the ellipse.
}
This way, you can hold the ellipse fill color in the CustomPanel class, and just call repaint() method after you change the color.
your idea could be very good described (including code example) in the Oracles tutorial How to Decorate Components with the JLayer Class
notice JLayer is available only for Java7, but its based on (for Java6) JXLayer
you can use (I'm using) GlassPane too, with the same / similair output to the Swing GUI
EDIT
quite easy and nice output is by using OverlayLayout, there is possible to overlay J/Component(s) with Graphics e.g., a few examples
take the two images as image icons like
ImageIcon car=new ImageIcon("image path");
ImageIcon elipse=new ImageIcon("image path");
add those two image icons two label
JLabel carLabel=new JLabel(car);
JLabel ellipseLabel=new JLabel(ellipse);
and set the position of ellipse and car
carLabel.setBounds(0,0,50,50);
ellipseLabel.setBounds(10,10,50,50);

How to rotate an image properly in JPanel (Java)

I'm working on rotating a loaded image. I set the graphics on a JPanel and then use standard AffineTransform in order to rotate it, say, 45 degrees.
Unfortunately, the image is being cut, if it exceeds the panel area.
How may I force JPanel to add scrolls to itself (while loading an image file, I would like to adjust the size of JPanel by adding the scrolls, without adjusting the size of JFrame).
Or, in other words, how to correctly rotate the whole image?
Thank you in advance for the reply!
Use a JScrollPane instead.
You need to put the panel in a jscrollPane and then make sure you have the preferredsize set correctly so that the scroll will be available.
Well, I would suggest that you should not be rotating the image in the paintComponent() method of your panel since this will result in the preferred size of the panel changing and you should not be setting the preferred size in the paintComponent() method.
Instead you should probably have a rotate(...) method. This method will create a BufferedImage of the desired rotation. Then your paintComponent() method simply paints the buffered image. Then you would set the preferred size based on the rotation.
Now regarding the preferred size of the rotated image check out this example.

Categories

Resources