---
category: swing
folder: AutoResizeTableHeader
title: JTableHeaderと各行の高さを親JScrollPaneが埋まるまで均等に自動調整
title-en: Auto adjusts the heights of JTableHeader and rows evenly to fill the parent JScrollPane
tags: [JTable, JTableHeader, JScrollPane, Calendar]
author: aterai
pubdate: 2025-12-01T00:16:26+09:00
description: JTableHeaderとJTableの行の高さの合計が親JScrollPaneの高さまを埋めるまで均等に自動拡大・縮小します。
summary-jp: JTableHeaderとJTableの行の高さの合計が親JScrollPaneの高さまを埋めるまで均等に自動拡大・縮小します。
summary-en: Automatically resize the JTableHeader and JTable rows evenly to fill the height of the parent JScrollPane.
image: https://drive.google.com/uc?id=1sN5ERINi9nhOhb5s5MmYFxwPfFLXt8fs
---
* Summary [#summary]
JTableHeaderとJTableの行の高さの合計が親JScrollPaneの高さを埋めるまで均等に自動拡大・縮小します。
`JTableHeader`と`JTable`の行の高さの合計が親`JScrollPane`の高さを埋めるまで均等に自動拡大・縮小します。
// #en{{Automatically resize the JTableHeader and JTable rows evenly to fill the height of the parent JScrollPane.}}
#download(https://drive.google.com/uc?id=1sN5ERINi9nhOhb5s5MmYFxwPfFLXt8fs)
* Source Code Examples [#sourcecode]
#code(link){{
class MonthTable extends JTable {
@Override protected JTableHeader createDefaultTableHeader() {
return new JTableHeader(columnModel) {
@Override public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
JTable tbl = getTable();
Container c = SwingUtilities.getAncestorOfClass(JScrollPane.class, tbl);
if (c instanceof JScrollPane) {
int rowCount = tbl.getModel().getRowCount() + 1;
Rectangle r = SwingUtilities.calculateInnerArea((JScrollPane) c, null);
d.height = Math.max(r.height / rowCount, 24);
}
return d;
}
};
}
@Override public void doLayout() {
super.doLayout();
Class<JViewport> clz = JViewport.class;
Optional.ofNullable(SwingUtilities.getAncestorOfClass(clz, this))
.filter(clz::isInstance).map(clz::cast)
.ifPresent(this::updateRowsHeight);
}
private void updateRowsHeight(JViewport viewport) {
int height = viewport.getExtentSize().height;
int rowCount = getModel().getRowCount();
int defaultRowHeight = height / rowCount;
int remainder = height % rowCount;
for (int i = 0; i < rowCount; i++) {
int a = defaultRowHeight + Math.min(1, Math.max(0, remainder--));
setRowHeight(i, Math.max(1, a));
}
}
// ...
}
}}
* Description [#description]
- `JScrollPane`の高さが変更された場合、`JScrollPane#doLayout()`内で`ScrollPaneLayout#layoutContainer(...)`が呼ばれ、`JTableHeader#getPreferredSize()`でヘッダのサイズを取得し、その高さや存在すればスクロールバーの高さなどを除去して`JViewport`の高さが決まる
- このため、このサンプルでは`JTableHeader#getPreferredSize()`をオーバーライドして`JTableHeader`の高さを`JScrollPane`の高さの`1/6`になるよう設定
-- 上記の分母`6`は`JTable`が`5`行と`JTableHeader`が`1`個の合計
-- [[JTableHeaderの高さを変更>Swing/TableHeaderHeight]]
- `JTable`の各行の高さは`JTable#doLayout()`をオーバーライドして`JViewport`の高さを満たすよう調整
-- [[JTableの行高がJViewportの高さに合うまで調整する>Swing/AdjustRowHeightFillsViewport]]
- 以下のように`JScrollPane#doLayout()`をオーバーライドして`JViewport`の高さを決めるまえに`JTableHeader`の高さを調整する方法もある
#code{{
class MonthScrollPane extends JScrollPane {
protected MonthScrollPane(Component view) {
super(view);
}
@Override public void updateUI() {
super.updateUI();
setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_NEVER);
}
@Override public void doLayout() {
JTable tbl = (JTable) getViewport().getView();
int rowCount = tbl.getModel().getRowCount() + 1;
JTableHeader header = tbl.getTableHeader();
Dimension d = header.getPreferredSize();
Rectangle r = SwingUtilities.calculateInnerArea(this, null);
d.height = Math.max(r.height / rowCount, 24);
header.setPreferredSize(d);
super.doLayout();
}
}
}}
* Reference [#reference]
- [[JTableHeaderの高さを変更>Swing/TableHeaderHeight]]
- [[JTableの行高がJViewportの高さに合うまで調整する>Swing/AdjustRowHeightFillsViewport]]
- [[JTableHeaderのヘッダカラムセルの背景色を変更>Swing/HeaderColumnBackground]]
-- カレンダー部分は上記のリンク先のサンプルを流用
* Comment [#comment]
#comment
#comment