Window Resize event

2019-09-06 11:48发布

I have a program that scales an image to the size of the screen. I currently have a component listener listening for a componentResized event, but this is not what I want. I would like the method to only be called one the user lift's there finger off their mouse, not as they are doing the resizing. This way, my image will not constantly be resizing to the user's specifications.

Thanks!

1条回答
可以哭但决不认输i
2楼-- · 2019-09-06 12:29

A solution is to supply a Swing Timer which is reset each time componentResized is called. This injects a small delay between the last resize event and the time you should perform the resize action.

import javax.swing.Timer;
//...
// Declare an instance variable...
private Timer resizeTimer;
//...
// Probably in you classes constructor
resizeTimer = new Timer(250, new ActionListener() {
    public void actionPerformed(ActionEvent evt) {
        // Actually perform the resizing of the image...
        resizeBackgroundImage();
    }
});
// Don't want a repeating event...
resizeTimer.setRepeats(false);

//...
public void componentResized(ComponentEvent evt) {
    resizeTimre.restart();
}

This basically, sets it up so that it will require 250 milliseconds between resize events before an attempt is made to resize the image. You can play around with the value to suit your own needs.

Updated with runnable example

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class RescaleTest {

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

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

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private BufferedImage master;
        private Image scaled;

        private Timer resizeTimer;

        public TestPane() {
            try {
                master = ImageIO.read(new File("/path/to/your/image"));
                scaled = master;
            } catch (IOException exp) {
                exp.printStackTrace();
            }

            resizeTimer = new Timer(250, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    resizeBackground();
                }
            });
            resizeTimer.setRepeats(false);

            addComponentListener(new ComponentAdapter() {

                @Override
                public void componentResized(ComponentEvent e) {
                    resizeTimer.restart();
                }

            });
        }

        protected void resizeBackground() {
            // This is not my preferred scaling process, I prefer to use
            // a divide and conqure approach and do so in the background
            // where possible, but this is beyond the scope of the question...
            if (getWidth() < getHeight()) {
                scaled = master.getScaledInstance(getWidth(), -1, Image.SCALE_SMOOTH);
            } else {
                scaled = master.getScaledInstance(-1, getHeight(), Image.SCALE_SMOOTH);
            }
            repaint();
        }

        @Override
        public Dimension getPreferredSize() {
            return master != null ? new Dimension(master.getWidth(), master.getHeight()) : new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (scaled != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                int x = (getWidth() - scaled.getWidth(this)) / 2;
                int y = (getHeight() - scaled.getHeight(this)) / 2;
                g2d.drawImage(scaled, x, y, this);
                g2d.dispose();
            }
        }
    }

}

nb: The scaling used in this example is not my preferred method and was done for demonstration purposes only. See The Perils of Image.getScaledInstance() for details and Scale the ImageIcon automatically to label size for an alterantive approach...

查看更多
登录 后发表回答