0

I am kind of stuck at maintaining aspect ratio on my JPanel.

I have default generated JFrame from Netbeans with Border layout. Whole frame is filled with my JPanel (from my custom class GraphicsPanel.java extending JPanel).

GraphicsPanel class have only one over ridden method for drawing graphics with some basic constructor. I have one rectangle and polygon on my JPanel. What I'm trying to achieve is when I re-size the frame I want to keep my JPanel on aspect ratio 4:3 (or something similar to it). When the frame is too big for aspect ratio it will fill the frame back ground with some default color.

I've read some topics about aspect ratio (for example this). But no luck and I still have no clue how to do it.

There's my code from my JPanel class. I'm beginner and I'm trying to learn how to work with Java graphics (draw, fill, resize etc) so please go easy on me.

import java.awt.Color;
import java.awt.Graphics;
public class GraphicsPanel extends javax.swing.JPanel {

private int x;
private int z;
private int y;

public GraphicsPanel() { //constructor
    initComponents();
    x = getHeight() / 2;
    z = getWidth() / 2;
    y = getHeight() - 1;
}

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);

        x = getHeight() / 2;
        z = getWidth() / 2;
        y = getHeight() - 1;

    setBackground(new Color(255, 255, 255));

    g.setColor(Color.red);
    g.fillRect(0, x, getWidth() - 1, y);

    g.setColor(Color.blue);
    int[] poleX = {0, 0, z};
    int[] poleY = {0, y, x};
    g.fillPolygon(poleX, poleY, 3);
  }
}

JFrame

Community
  • 1
  • 1
Bukk94
  • 419
  • 1
  • 6
  • 23
  • You want the image or the component to maintain it's ratio? – MadProgrammer Oct 15 '15 at 08:27
  • I need to maintain image that I'm drawing (but I guess it will be easier to maintain component's ratio). Because my image is not classic image (png, jpg) but a few shapes from draw/fill that looks like an image. – Bukk94 Oct 15 '15 at 08:31
  • *"I need to maintain image that I'm drawing (but I guess it will be easier to maintain component's ratio)."* I've done the first many times, using a combination of `AffineTransform` instances. The 2nd I've only attempted once, in [Making a robust, resizable Swing Chess GUI](http://stackoverflow.com/q/21142686/418556). **I'd recommend the first approach over the 2nd.** – Andrew Thompson Oct 15 '15 at 08:40
  • I think you'll find it easier to maintain the ratio of what you paint over trying to control the layout – MadProgrammer Oct 15 '15 at 08:57
  • I've already tried it but with no success. I'm at dead end and I have no clue how to continue. I tried some if statements and listeners but it was weird. – Bukk94 Oct 15 '15 at 10:45
  • For [example](http://stackoverflow.com/a/9858355/230513). – trashgod Oct 15 '15 at 11:47

2 Answers2

1

I think that what you want is to paint your image (which looks a lot like the Czech flag!) in your panel, but not filling all of the space. For example, if the frame is very wide, the image will not fill the whole width. If I understood correctly, this isn't so hard.

In you code, you get the width and height of the panel. When you've done that, do some arithmetic. If the aspect ratio is "too wide" then your image will fill the height, otherwise it will fill the width. Now you know one dimension, so you can calculate the other, and you only draw the image big enough to fit inside those dimensions.

Edit: example calculations...

if panel width / panel height > 4 / 3
    // too wide
    // use panel height as image height
    // calculate image width from image height
else
    // use panel width as image width
    // calculate image height from image width

The size and shape of a panel is hard (impossible?) to fix. You must add the panel to a container (JFrame in your example, but could be anything), and the container will use a layout manager to set the panel size.

Jonathan
  • 349
  • 1
  • 9
  • Yes, that's exactly what i need. And yes, it's Czech flag :) I know it's not hard but I'm having hard times with setting conditions for filling / calculatin dimensions. – Bukk94 Oct 15 '15 at 11:51
  • I added example calculations. – Jonathan Oct 16 '15 at 09:09
  • Yes! That's exactly what I've needed. Simple and fast solution for my studying. Thanks a lot for calculations and clues! It's working exactly how I wanted :) – Bukk94 Oct 16 '15 at 19:51
1

I need to maintain image that I'm drawing (but I guess it will be easier to maintain component's ratio). Because my image is not classic image (png, jpg) but a few shapes from draw/fill that looks like an image.

Well you can easily create a BufferedImage at some reasonable size, in the proper aspect ratio, and draw your shapes onto the BufferedImage

BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = image.createGraphics();

//  paint image background

g2d.setColor( ... );
g2d.fillRect(0, 0, width, height);

//  draw shapes

g2d.fillOval(....);

The you can use Darryls Stretch Icon to display the image in a JLabel. The StretchIcon class will scale the Icon proportionally within the space available to the label:

JLabel label = new JLabel( new StretchIcon(image) );
frame.add(label);
camickr
  • 321,443
  • 19
  • 166
  • 288
  • Thanks for your effort but I think this is too advanced for me :) – Bukk94 Oct 16 '15 at 19:51
  • @Shocky, I don't know how it can be too advanced since you don't have to do anything special. All you do is paint the flag at a given size. The StretchIcon does the rest. It is an easier and more reusable solution than the one you are using now. While I agree you may want to use your current approach (as a learning tool), you should still understand this approach as it demonstrates the power of creating/using reusable code. So I suggest you also get this approach working to understand the differences/benefits of both approaches. – camickr Oct 16 '15 at 20:11
  • Sure I'll take a look at your approach too. But I never worked with StrechIcon or BufferedImage so that's why I wanted some simple solution. – Bukk94 Oct 18 '15 at 11:04
  • `I wanted some simple solution.` - how do you know what is simple, if you don't try both? I gave you the code for a BufferedImage. It is no different painting on a BufferedImage then it is painting in the paintComponent() method. – camickr Oct 18 '15 at 17:05