0

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!

Chris Smith
  • 2,928
  • 4
  • 27
  • 59
  • Have you tried MouseListener (or MouseAdapter) and implement the mouseReleased(MouseEvent e) method? Then, obtain the new size and redraw your image on the new size? – anonymous Mar 05 '14 at 00:32
  • I was considering that, but then on every click the stuff would attempt to resize. – Chris Smith Mar 05 '14 at 00:34

2 Answers2

0

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...

Community
  • 1
  • 1
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
0

If you put Toolkit.getDefaultToolkit().setDynamicLayout(false); right inside of main it will disable the frame from updating dynamically as you increase/decrease it's size. The ui will only be updated after you stop resizing.

import MainMenu.GameManager;

import java.awt.*;
import java.io.IOException;

public class Main {

    Main(){

    }
        public static void main(String[] args) throws IOException {
            GameManager manager = new GameManager();
            Toolkit.getDefaultToolkit().setDynamicLayout(false);
        }
    }
Bwizz
  • 81
  • 6