如何在用户完成JFrame窗口拖拽缩放后执行指定代码?
问题根因
你之前用Timer延迟触发的方案缺陷在于,没有区分「用户拖拽中暂时停止移动鼠标」和「用户完成缩放松开鼠标」两种场景,只要缩放事件中断达到400ms就会触发逻辑,不符合需求。
可行实现方案
我们可以通过组合鼠标事件监听+调整状态标记的方式,精准识别用户松开鼠标完成缩放的时机,同时兼容系统触发的窗口缩放(最大化/还原等)场景。
完整实现代码
import javax.swing.*; import java.awt.*; import java.awt.event.*; public class Gui { private JFrame frame; // 标记是否正处于用户拖拽调整窗口大小的状态 private boolean isResizing = false; // 处理非拖拽场景的缩放防抖Timer,延迟可自行调整 private final Timer resizeDebounceTimer = new Timer(150, e -> handleResizeFinish()); public Gui() { frame = new JFrame("缩放测试窗口"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(400, 300); frame.setVisible(true); // 初始化Timer:不重复触发 resizeDebounceTimer.setRepeats(false); // 1. 全局监听鼠标事件,识别缩放拖拽的开始和结束 AWTEventListener mouseListener = event -> { if (event instanceof MouseEvent mouseEvent) { // 鼠标左键按下,且当前光标不是默认样式(说明点在了窗口边框可拖拽区域) if (mouseEvent.getID() == MouseEvent.MOUSE_PRESSED && SwingUtilities.isLeftMouseButton(mouseEvent)) { if (frame.getCursor().getType() != Cursor.DEFAULT_CURSOR) { isResizing = true; } } // 鼠标左键释放,且之前处于缩放状态,说明完成拖拽缩放 else if (mouseEvent.getID() == MouseEvent.MOUSE_RELEASED && SwingUtilities.isLeftMouseButton(mouseEvent)) { if (isResizing) { isResizing = false; handleResizeFinish(); } } } }; // 注册鼠标事件监听 Toolkit.getDefaultToolkit().addAWTEventListener(mouseListener, AWTEvent.MOUSE_EVENT_MASK); // 2. 监听窗口缩放事件,处理非拖拽的缩放场景(最大化、还原、快捷键调整大小等) frame.getRootPane().addComponentListener(new ComponentAdapter() { @Override public void componentResized(ComponentEvent e) { // 如果不是用户拖拽触发的缩放,用Timer防抖后执行逻辑 if (!isResizing) { resizeDebounceTimer.restart(); } } }); // 3. 窗口销毁时移除全局监听,避免内存泄漏 frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { Toolkit.getDefaultToolkit().removeAWTEventListener(mouseListener); } }); } // 缩放完成后要执行的逻辑写在这里 private void handleResizeFinish() { // 你的自定义逻辑 System.out.println("窗口缩放完成,当前尺寸:" + frame.getWidth() + "x" + frame.getHeight()); } public static void main(String[] args) { SwingUtilities.invokeLater(Gui::new); } }
效果说明
- 拖拽边框调整大小:只有松开鼠标左键时才会触发
handleResizeFinish方法,拖拽中途停止移动鼠标不会触发 - 点击最大化/还原按钮、用系统快捷键调整窗口大小:会通过防抖Timer触发逻辑,避免多次调用
- 无多余触发,性能开销极低
布局效果参考
小尺寸布局:
扩展后的布局:
内容的提问来源于stack exchange,提问作者65_7a
相关产品推荐
相关产品推荐

