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

如何编写JPanel代码使绘制的图形始终完整可见?

解决Swing中FlowLayout下SchedulePanel网格只显示右上角的问题

问题场景

开发事件调度系统时,自定义的SchedulePanel绘制网格,但添加到使用FlowLayout的主面板后,仅能看到网格右上角,无法完整显示。

原SchedulePanel代码:

public class SchedulePanel extends JPanel {

        private static final long serialVersionUID = 1L;

        static final int originX = 0;
        static final int originY = 0;
        static final int cellSide = 50;

        static final int cols = 5;
        static final int rows = 5;

        public SchedulePanel() {
            setMinimumSize(new Dimension(cols * cellSide, rows * cellSide));
            setBackground(Color.LIGHT_GRAY);
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            // 绘制分隔行的水平线
            for (int i = 0; i < rows; i++) {
                g.drawLine(originX, originY + (i * cellSide),
                        originX + (cols * cellSide), originY + (i * cellSide));
            }
            // 绘制分隔列的垂直线
            for (int i = 0; i < cols; i++) {
                g.drawLine(originX + (i * cellSide), originY,
                        originX + (i * cellSide), originY + (rows * cellSide));
            }

        }
    }

主面板代码:

public class EventSchedulerGUI extends JPanel {

    RoomPanel roomPanel;
    SchedulePanel schedulePanel;
    JList<Room> roomList;

    public EventSchedulerGUI() {
        FlowLayout layout = new FlowLayout();
        setLayout(layout);
        roomPanel = new RoomPanel();

        schedulePanel = new SchedulePanel();
        schedulePanel.setMinimumSize(new Dimension(400, 400));

        add(roomPanel);
        add(schedulePanel);

    }

问题原因

  1. FlowLayout的尺寸优先级:FlowLayout会优先使用组件的preferredSize分配空间,仅设置minimumSize不会被该布局管理器优先考虑,导致SchedulePanel被压缩到极小,仅显示局部内容。
  2. 绘制循环逻辑缺陷:原代码中绘制水平线和垂直线的循环条件为i < rows/i < cols,这会漏掉最后一条边框线(比如5行网格需要6条水平线才能分隔出5个完整单元格)。

解决方案

1. 重写SchedulePanel的getPreferredSize方法

让组件主动向布局管理器提供正确的首选尺寸,替代仅设置minimumSize的方式。

2. 修正绘制循环的边界条件

确保完整绘制所有网格边框线。

3. 移除主面板中多余的minimumSize设置

让组件自身的尺寸逻辑生效。

修改后的SchedulePanel代码:

public class SchedulePanel extends JPanel {

    private static final long serialVersionUID = 1L;

    static final int originX = 0;
    static final int originY = 0;
    static final int cellSide = 50;

    static final int cols = 5;
    static final int rows = 5;

    public SchedulePanel() {
        setBackground(Color.LIGHT_GRAY);
    }

    // 重写getPreferredSize,提供正确的首选尺寸
    @Override
    public Dimension getPreferredSize() {
        return new Dimension(cols * cellSide, rows * cellSide);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        // 绘制分隔行的水平线,修正循环条件为i <= rows
        for (int i = 0; i <= rows; i++) {
            g.drawLine(originX, originY + (i * cellSide),
                    originX + (cols * cellSide), originY + (i * cellSide));
        }
        // 绘制分隔列的垂直线,修正循环条件为i <= cols
        for (int i = 0; i <= cols; i++) {
            g.drawLine(originX + (i * cellSide), originY,
                    originX + (i * cellSide), originY + (rows * cellSide));
        }
    }
}

修改后的主面板代码:

public class EventSchedulerGUI extends JPanel {

    RoomPanel roomPanel;
    SchedulePanel schedulePanel;
    JList<Room> roomList;

    public EventSchedulerGUI() {
        setLayout(new FlowLayout());
        roomPanel = new RoomPanel();
        schedulePanel = new SchedulePanel();

        add(roomPanel);
        add(schedulePanel);
    }
}

可选优化:添加滚动支持

如果窗口尺寸可能小于网格尺寸,可以将SchedulePanel放入JScrollPane中,实现滚动查看:

// 在主面板中替换add(schedulePanel)为:
add(new JScrollPane(schedulePanel));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 20:15:00