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

Java Swing绘图位置错误:窗口尺寸与组件实际宽度不符问题

Swing组件宽度未匹配窗口设置尺寸的原因

问题现象

运行以下代码后,绘制的矩形位置偏右;调用getWidth()发现TestPane的实际宽度仅为984,而非窗口设置的1000像素。按Swing文档描述,该组件应占据剩余空间,理论宽度应为1000,请问原因是什么?

错误位置矩形示意图

可复现代码

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;


public class TestStackOverflow {

    public static void main(String[] args) {
        new TestStackOverflow();
    }
    
    public TestStackOverflow() {
        EventQueue.invokeLater(new Runnable() {
            
            @Override
            public void run() {
                JFrame window = new JFrame();
                window.setSize(new Dimension(1000, 1000));
                window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                
                JPanel header = new JPanel();
                header.add(new JLabel("Hello, I'm the header"));
                header.setBackground(Color.red);
                
                window.add(header, BorderLayout.NORTH);
                window.add(new TestPane());
                
                window.setLocationRelativeTo(null);
                window.setVisible(true);
            }
        });
    }
    
    public class TestPane extends JPanel {
        public TestPane() {
            setBackground(Color.blue);
        }
        
        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawRect(900, 0, 100, 100);
            //System.out.println(getWidth());       
        }
    }
}

原因解析

核心原因是**JFrame.setSize()设置的是整个窗口的完整尺寸(包含标题栏、边框等系统装饰区域),而非窗口内部内容面板的尺寸**。

  • 当调用window.setSize(new Dimension(1000, 1000))时,这1000像素的宽度包含了窗口左右边框的总宽度(不同系统/主题下装饰区域尺寸略有差异,这里总宽度差为16像素),因此内容面板的实际可用宽度是1000 - 边框总宽度 = 984像素。
  • TestPane作为BorderLayout.CENTER区域的组件,会自动填充内容面板的剩余空间,所以它的宽度等于内容面板的实际宽度,也就是984像素,导致绘制的矩形偏右。

解决方案

如果需要让TestPane的宽度达到预期的1000像素,可以采用以下两种方式:

方式一:使用pack()结合设置组件首选尺寸

修改代码,给TestPane设置首选尺寸,然后调用pack()让窗口自动适配:

// 在TestPane的构造方法中添加
setPreferredSize(new Dimension(1000, 900)); // 900为扣除header高度后的预期高度

// 将window.setSize(...)替换为
window.pack();

方式二:手动计算装饰区域尺寸,调整窗口大小

先获取窗口的装饰区域边距,再设置窗口尺寸以保证内容面板达到预期大小:

// 在设置窗口尺寸前先获取Insets
Insets insets = window.getInsets();
// 窗口总宽度 = 内容面板预期宽度 + 左右边框宽度;总高度同理
window.setSize(1000 + insets.left + insets.right, 1000 + insets.top + insets.bottom);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 23:35:22