Skip to content

How to scale basic drawings?

I would like to have a list of shapes, that appears in my window. Whenever I’m changing the size of the window, I would like to scale all of my drawings.

I already prepared classes, that store information about random shapes in a list (rectangles, ovals, etc.). I have no problem with painting them all, but I can’t deal with the scaling problem. My solutions don’t change anything, or make all of shapes disappear.

public class Shape extends JPanel{
    int x, y,width,height,red,green,blue;
    double scX, scY; //scale x and y

    public Shape(int x, int y, int width, int height, int red, int green, int blue) {
//...long constructor
        scX=1;
        scY=1;
    }
    void randomizeValues(){...}

        void setScale(double x, double y) {
        this.scX = x;
        this.scY = y;
    }
}

public class Rectangle extends Shape{

    public Rectangle(int x, int y, int width, int height, int red, int green, int blue) {
        super(x, y, width, height, red, green, blue);
    }

    @Override
    protected void paintComponent(Graphics graphics) {
        super.paintComponent(graphics);
        graphics.fillRect((int)(x*scX), (int)(y*scY), (int)(width*scX), (int)(height*scY));
    }
}


class Window extends JFrame {

    int defaultWidth = 768;
    int defaultHeight = 512;
    List<Shape> paintList = new ArrayList<>();

 public Window() {
        setTitle("Shape");
        add(new DrawShape);
        setSize(defaultWidth, defaultHeight);
        setVisible(true);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    }

class DrawShape extends JPanel {
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            for (int i = 0; i< paintList.size(); i++) {
                Shape s = paintList.get(i);
                s.setScale(this.getWidth()/defaultWidth, this.getHeight()/defaultHeight);
                s.paintComponent(g);
            }
   }
}

How to make a proper scale trick? Where should I multiply values, to make everything work good?

Answer

First of all, you should not add your JPanel to your window but set it as the ContentPane : setContentPane(new DrawShape());. Next, you should not repaint inside the loop but outside (at the end of your paintComponent(Graphics g) method for example). This way, the JPanel should be drawn again permanently. If you need to change the size of your shapes depending on the window dimension, do it like that in your JPanel paintComponent(Graphics g) method:

//fill it with the shapes base sizes (index 0 = width, index 1 = height)
Map<Shape,int[]> shapeSizes = new HashMap<Shape,int[]>();
public void paintComponent(Graphics g) {
double widthCoeff = this.getWidth()/(double)Window.this.defaultWidth;
double heightCoeff = this.getHeight()/(double)Window.this.defaultHeight;
for (int i = 0; i< paintList.size(); i++) {
Shape s = paintList.get(i);
int[] baseSize = shapeSizes.get(s);
int oldWidth = baseSize[0], oldHeight = baseSize[1];
int width = oldWidth*widthCoeff, height = oldHeight*heightCoeff;
//you can now give the shape its new width and height
}
}