How do I resize images inside an application when

2020-01-25 12:01发布

问题:

When I maximize my application, the images inside of the JPanel don't resize with it. How can I make the JPanel and its contents adjust when the window is maximized?

EDIT: I am using BufferedImage

回答1:

That's an open ended question.

Do you want to scale to fill or scale to fit the area or don't you care about the aspect ratio??

The difference between scale to fill and scale to fit

This example will react to changes in the size of the frame and rescale the image in real time.

public class TestScaling {

    public static void main(String[] args) {
        new TestScaling();
    }

    public TestScaling() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new ScalingPane());
                frame.setSize(200, 200);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }

        });
    }

    public class ScalingPane extends javax.swing.JPanel {

        private BufferedImage image;

        public ScalingPane() {
            try {
                image = ImageIO.read(getClass().getResource("/AtDesk.png"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }    
            setBackground(Color.red);
        }

        public double getScaleFactor(int iMasterSize, int iTargetSize) {    
            double dScale = 1;
            dScale = (double) iTargetSize / (double) iMasterSize;

            return dScale;    
        }

        public double getScaleFactorToFit(Dimension original, Dimension toFit) {    
            double dScale = 1d;

            if (original != null && toFit != null) {    
                double dScaleWidth = getScaleFactor(original.width, toFit.width);
                double dScaleHeight = getScaleFactor(original.height, toFit.height);

                dScale = Math.min(dScaleHeight, dScaleWidth);
            }    
            return dScale;
        }

        public double getScaleFactorToFill(Dimension masterSize, Dimension targetSize) {
            double dScaleWidth = getScaleFactor(masterSize.width, targetSize.width);
            double dScaleHeight = getScaleFactor(masterSize.height, targetSize.height);

            double dScale = Math.max(dScaleHeight, dScaleWidth);

            return dScale;
        }

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

            double scaleFactor = Math.min(1d, getScaleFactorToFit(new Dimension(image.getWidth(), image.getHeight()), getSize()));
//            double scaleFactor = Math.min(1d, getScaleFactorToFill(new Dimension(image.getWidth(), image.getHeight()), getSize()));

            int scaleWidth = (int) Math.round(image.getWidth() * scaleFactor);
            int scaleHeight = (int) Math.round(image.getHeight() * scaleFactor);

            Image scaled = image.getScaledInstance(scaleWidth, scaleHeight, Image.SCALE_SMOOTH);

            int width = getWidth() - 1;
            int height = getHeight() - 1;

            int x = (width - scaled.getWidth(this)) / 2;
            int y = (height - scaled.getHeight(this)) / 2;

            g.drawImage(scaled, x, y, this);
        }
    }
}

A better solution would be to have a background thread of some kind that could react to changes in the size of the component and rescale the original image in the background, providing a low quality and high quality scale.

It should also be noted that Image.getScaledInstance is neither the fastest or highest quality scaling algorithim. Take a look at The Perils of Image.getScaledInstance for more information.

You might also find the following of interest

Java: maintaining aspect ratio of JPanel background image



回答2:

One crude way..

public void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.draw(image,0,0,getWidth(),getHeight(),this);
    // ..