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

如何在调整JComponent大小时保持其中心点位置不变

核心计算逻辑

要保证调整尺寸时组件中心点固定,只需提前记录初始状态下的固定中心点坐标,调整后用中心点反推新的左上角坐标即可,计算公式如下:

  • 初始固定中心点:fixedCx = 初始x坐标 + 初始宽度 / 2,fixedCy = 初始y坐标 + 初始高度 / 2
  • 调整尺寸后新的左上角坐标:newX = fixedCx - 新宽度 / 2,newY = fixedCy - 新高度 / 2
具体实现步骤
  • 组件初始化完成后,提前计算并存储固定的中心点坐标,不要在每次尺寸调整时动态计算当前中心点,否则会出现累计偏移
  • 每次触发滑块调整事件时,先计算调整后的新宽度、新高度
  • 用上述公式计算新的左上角x、y坐标
  • 调用setBounds()方法一次性更新组件的坐标和尺寸,不要分开调用setSize()和setLocation(),避免出现闪烁错位
适配修改后的代码

你原有代码存在两个问题:一是滑块的最大最小值配置错误导致无法拖动,二是仅更新尺寸没有同步调整坐标,以下是修改后的核心逻辑(仅列出JButtonExperiments的Print方法,其余代码保持不变即可):

class JButtonExperiments
{
    public static void Print()
    {
        JFrame frame = new JFrame();
        frame.setLayout(null);
        frame.setSize(1200, 1200);
        JButton B = new JButton("w");
        int initialWidth = 160;
        int initialHeight = 160;
        B.setBounds(600, 600, initialWidth, initialHeight);
        // 存储固定的中心点坐标,后续调整尺寸时不会变更
        int fixedCx = B.getX() + initialWidth / 2;
        int fixedCy = B.getY() + initialHeight / 2;
        B.setText(new Scanner(System.in).nextLine());
        frame.add(B);
        // 修正滑块构造参数:顺序为方向、最小值、最大值、初始值
        JSlider widthSlider = new JSlider(SwingConstants.VERTICAL, 0, 400, 0);
        JSlider heightSlider = new JSlider(SwingConstants.VERTICAL, 0, 400, 0);
        widthSlider.setLocation(200, 600);
        JLabel widthBox = new JLabel("Width");
        widthBox.setBounds(20, 500, 120, 120);
        heightSlider.setLocation(1000, 600);
        JLabel heightBox = new JLabel("Height");
        heightBox.setBounds(1100, 500, 120, 120);
        widthSlider.setSize(100, 600);
        heightSlider.setSize(100, 600);
        frame.add(widthBox);
        frame.add(heightBox);
        frame.setVisible(true);
        AtomicInteger counter = new AtomicInteger();
        B.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                counter.getAndIncrement();
                if(counter.get() == 1)
                {
                    frame.add(widthSlider);
                    frame.add(heightSlider);
                    frame.repaint();
                }
                if(counter.get() == 3)
                {
                    widthSlider.addChangeListener(E ->
                    {
                        int newWidth = initialWidth + widthSlider.getValue();
                        int newHeight = initialHeight + heightSlider.getValue();
                        int newX = fixedCx - newWidth / 2;
                        int newY = fixedCy - newHeight / 2;
                        B.setBounds(newX, newY, newWidth, newHeight);
                    }
                    );

                    heightSlider.addChangeListener(E ->
                    {
                        int newWidth = initialWidth + widthSlider.getValue();
                        int newHeight = initialHeight + heightSlider.getValue();
                        int newX = fixedCx - newWidth / 2;
                        int newY = fixedCy - newHeight / 2;
                        B.setBounds(newX, newY, newWidth, newHeight);
                    }
                    );
                }

            }
        });
    }
}
注意事项
  • 这里采用「初始宽高+滑块值」计算新尺寸,比每次叠加当前尺寸更稳定,不会出现累计误差
  • 必须一次性调用setBounds更新坐标和尺寸,分开调用会导致组件先拉伸再移动,出现肉眼可见的闪烁
  • 如果后续要修改按钮初始位置,只需要调整setBounds的初始参数,中心点会自动计算无需手动修改

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 17:54:05