简体   繁体   中英

Rescale a drawing in Java (JFrame)

I need the simplest way to rescale a drawing in java (for example a rectangle...). I found a way to "stretch" them:

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import java.awt.Dimension;

public class Stretch extends JFrame {
    int originalHeight = 600;
    int originalWidth = 600;
    public Stretch() {
        super("Stretch");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(originalWidth, originalHeight);
    }
    public static void main(String[] args) {
        Stretch s = new Stretch();
        s.setVisible(true);
    }
    public void paint(Graphics g) {
        Dimension size = this.getBounds().getSize();
        int rectWidth = 100;
        int rectHeight = 130;

        g.setColor(Color.white);
        g.fillRect(0, 0, size.width, size.height);

        g.setColor(Color.black);
        g.drawRect(100, 100, rectWidth + size.width - originalWidth, rectHeight + size.height - originalHeight);

    }
}

As you can see the formula is like that:

g.drawRect(100, 100, rectWidth + size.width - originalWidth, rectHeight + size.height - originalHeight);

Now how can I rescale the drawing? Width and height have to maintain the same proportion. Thank you.

There are bascially two different approaches for this:

  • You can "scale the whole Graphics "
  • You can scale the actual shapes

The difference may be subtle in some cases, but can be important: When you scale the whole Graphics , then everything will be scaled. Particularly, when you scale it about 2.0 , and then draw a line with a width of 1.0 , the line will be drawn 2 pixels wide. Whether or not this is desired depends on the application case.

In order to scale the actual shapes, you can not use the drawRect method. Instead you will have to create Shape instances that represent the geometric shapes. You can then create scaled versions of these shapes with AffineTransform#createTransformedShape .

Here is an example that compares both approaches (and corrects some of the other issues that have been in your code). In both cases, the same rectangle with an original size of (10,13) is painted, scaled by a factor of 5.0.

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class ScalingDrawnObjects
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI()
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        ScalingDrawnObjectsPanel p = new ScalingDrawnObjectsPanel();
        f.getContentPane().add(p);
        f.setSize(600,400);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}

class ScalingDrawnObjectsPanel extends JPanel
{
    @Override
    protected void paintComponent(Graphics gr)
    {
        super.paintComponent(gr);
        Graphics2D g = (Graphics2D)gr;

        Shape rectangle = new Rectangle2D.Double(2, 2, 10, 13);

        g.setColor(Color.RED);
        drawWithScaledGraphics(g, rectangle);

        g.translate(100, 0);

        drawScaledObject(g, rectangle);
    }

    private static void drawWithScaledGraphics(Graphics2D g, Shape shape)
    {
        AffineTransform oldAt = g.getTransform();
        g.scale(5.0, 5.0);
        g.draw(shape);
        g.setTransform(oldAt);
    }

    private static void drawScaledObject(Graphics2D g, Shape shape)
    {
        AffineTransform at = AffineTransform.getScaleInstance(5.0, 5.0);
        g.draw(at.createTransformedShape(shape));
    }

}

EDIT In response to the comment

The code that I posted is not "complicated". It is as compilcated as it has to be, but not more. You should not extend JFrame and you should not override paint . You should create the GUI on the EDT. You should ...

However, you should not use code like the following, but maybe this is what you're looking for

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import java.awt.Dimension;

public class Stretch extends JFrame {
    int originalHeight = 600;
    int originalWidth = 600;
    public Stretch() {
        super("Stretch");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(originalWidth, originalHeight);
    }
    public static void main(String[] args) {
        Stretch s = new Stretch();
        s.setVisible(true);
    }
    public void paint(Graphics g) {
        Dimension size = this.getBounds().getSize();
        int rectWidth = 100;
        int rectHeight = 130;

        g.setColor(Color.white);
        g.fillRect(0, 0, size.width, size.height);

        g.setColor(Color.black);

        int w = rectWidth + size.width - originalWidth;
        int h = rectHeight + size.height - originalHeight;
        double sx = (double)w / rectWidth;
        double sy = (double)h / rectHeight;
        double s = Math.min(sx, sy);
        int fw = (int)(s * rectWidth);
        int fh = (int)(s * rectHeight);
        g.drawRect(100, 100, fw, fh);

    }
}

How about multiplying the width and the height by the scale you want?

So if you want to scale it by 2:

g.drawRect(100, 100, 2 * (rectWidth + size.width - originalWidth), 2 * (rectHeight + size.height - originalHeight));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM