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

Java Swing中如何仅在鼠标释放时输出JFrame的X,Y,W,H

解决JFrame移动/调整大小时仅在操作结束后保存位置和尺寸的问题

原代码中ComponentListener的componentMoved和componentResized方法会在窗口移动或调整大小的过程中频繁触发,导致多次输出无效的中间状态。要实现仅在操作结束(鼠标释放、窗口状态稳定)后保存最终的位置和尺寸,最可靠的方式是通过延迟触发的逻辑:每次组件事件触发时重置延迟计时器,只有当用户停止操作、延迟到期后,才执行最终的保存操作。

修改后的完整代码

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class MouseMotionEventDemo extends JPanel {
    static JFrame frame = new JFrame();
    // 延迟计时器,设置300ms延迟(可根据需求调整)
    private Timer saveTimer;

    public MouseMotionEventDemo() {
        setPreferredSize(new Dimension(500, 300));
        
        // 初始化计时器:延迟300ms,到期后执行保存操作
        saveTimer = new Timer(300, e -> saveXYWH(frame));
        // 设置只执行一次
        saveTimer.setRepeats(false);

        frame.addComponentListener(new ComponentListener() {
            @Override
            public void componentResized(ComponentEvent e) {
                // 每次触发事件时重置计时器
                resetTimer();
            }

            @Override
            public void componentMoved(ComponentEvent e) {
                // 每次触发事件时重置计时器
                resetTimer();
            }

            @Override
            public void componentShown(ComponentEvent e) {}

            @Override
            public void componentHidden(ComponentEvent e) {}
        });
    }

    // 重置计时器:停止现有计时,重新启动
    private void resetTimer() {
        saveTimer.stop();
        saveTimer.start();
    }

    void saveXYWH(JFrame frame) {
        System.out.println("Demo [ X = " + frame.getLocation().x + " , Y = " + frame.getLocation().y + " | W = " + frame.getSize().width + " , H = " + frame.getSize().height + " ]");
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(() -> createAndShowGUI());
    }

    private static void createAndShowGUI() {
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        MouseMotionEventDemo demo = new MouseMotionEventDemo();
        frame.setContentPane(demo);
        frame.setLocationRelativeTo(null);
        frame.pack();
        frame.setVisible(true);
    }
}

关键逻辑说明

  1. 延迟计时器:使用javax.swing.Timer设置300毫秒的延迟(这个值可以根据实际体验调整,比如200-500ms都可以),确保用户停止操作后才触发保存。
  2. 重置计时器:每次componentMoved或componentResized触发时,先停止当前的计时器再重新启动。这样在用户持续拖动窗口时,计时器会不断被重置,只有当用户松开鼠标、窗口稳定后,计时器才会到期执行保存。
  3. 避免系统组件监听问题:JFrame的标题栏属于系统原生组件,无法直接通过Swing的鼠标监听器捕获释放事件,而延迟计时器的方式可以绕过这个限制,兼容所有平台。

内容的提问来源于stack exchange,提问作者Frank

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 21:13:31