You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在用户完成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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 01:09:03