【问题标题】:Window Resize event窗口调整大小事件
【发布时间】:2014-04-06 19:43:21
【问题描述】:

我有一个程序可以将图像缩放到屏幕大小。我目前有一个组件侦听器正在侦听 componentResized 事件,但这不是我想要的。我希望该方法仅被称为用户将手指从鼠标上移开的一种,而不是在他们进行调整大小时。这样,我的图像就不会根据用户的规格不断调整大小。

谢谢!

【问题讨论】:

  • 你试过 MouseListener(或 MouseAdapter)并实现 mouseReleased(MouseEvent e) 方法吗?然后,获取新尺寸并在新尺寸上重新绘制图像?
  • 我正在考虑这一点,但每次点击时,这些东西都会尝试调整大小。

标签: java resize window components listener


【解决方案1】:

解决方案是提供一个 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...

【讨论】:

【解决方案2】:

如果您将 Toolkit.getDefaultToolkit().setDynamicLayout(false); 放在 main 内部,它将禁用框架在您增加/减小其大小时动态更新。用户界面只会在您停止调整大小后更新。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-13
    • 2017-04-26
    • 2018-12-13
    • 2016-06-02
    相关资源
    最近更新 更多