Window Resize事件

时间:2014-03-05 00:26:19

标签: java resize window components listener

我有一个程序可以将图像缩放到屏幕大小。我目前有一个组件监听器监听componentResized事件,但这不是我想要的。我希望这个方法只能被称为一个用户抬起手指离开他们的鼠标,而不是他们正在调整大小。这样,我的图像就不会一直根据用户的规格调整大小。

谢谢!

2 个答案:

答案 0 :(得分:0)

解决方案是提供Swing Timer,每次调用componentResized时都会重置。这会在最后一次调整大小事件和执行调整大小操作的时间之间注入一个小延迟。

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();
}

这基本上设置它,以便在尝试调整图像大小之前在调整大小事件之间需要250毫秒。你可以随意使用它来满足自己的需求。

已更新为可运行示例

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 Perils of Image.getScaledInstance();有关替代方法,请参见Scale the ImageIcon automatically to label size ...

答案 1 :(得分:0)

如果将Toolkit.getDefaultToolkit().setDynamicLayout(false);放在main的内部,则当您增加/减小其大小时,该框架将无法动态更新。 ui只会在您停止调整大小后才更新。

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);
        }
    }