---
category: swing
folder: MonospacedTextField
title: JFormattedTextFieldに等幅フォントを設定する
tags: [JFormattedTextField, JTextField, Font]
author: aterai
pubdate: 2023-10-16T03:32:20+09:00
description: JFormattedTextFieldやJTextFieldの推奨サイズを列数とフォントのサイズから計算します。
image: https://drive.google.com/uc?id=1zsVcOAr0GDuWKenXy9aBptvPnqJHd53b
---
* Summary [#summary]
`JFormattedTextField`や`JTextField`の推奨サイズを列数とフォントのサイズから計算します。
#download(https://drive.google.com/uc?id=1zsVcOAr0GDuWKenXy9aBptvPnqJHd53b)
* Source Code Examples [#sourcecode]
#code(link){{
String code = "BC89FE5A";
JFormattedTextField field0 = new JFormattedTextField(code);
field0.setHorizontalAlignment(SwingConstants.RIGHT);
field0.setColumns(8);
JFormattedTextField field1 = new JFormattedTextField(code);
field1.setHorizontalAlignment(SwingConstants.RIGHT);
Font mono = new Font(Font.MONOSPACED, Font.PLAIN, field1.getFont().getSize());
field1.setFont(mono);
field1.setColumns(8);
JFormattedTextField field2 = new JFormattedTextField(code);
field2.setHorizontalAlignment(SwingConstants.RIGHT);
Map<TextAttribute, Object> attr = new ConcurrentHashMap<>();
attr.put(TextAttribute.TRACKING, -.021f);
field2.setFont(mono.deriveFont(attr));
field2.setColumns(8);
JFormattedTextField field3 = new JFormattedTextField(code) {
@Override public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
d.width += 2;
return d;
}
};
field3.setHorizontalAlignment(SwingConstants.RIGHT);
field3.setFont(mono);
field3.setColumns(8);
JFormattedTextField field4 = new JFormattedTextField(code);
field4.setHorizontalAlignment(SwingConstants.RIGHT);
field4.setFont(mono);
field4.setColumns(9);
}}
* Description [#explanation]
* Description [#description]
- `Default`
-- 日本語`Windows`環境のデフォルトでは`12px`の`MS UI Gothic`が使用され、小文字`m`の幅が`9px`(`12/2=6px`にならない)となるので、余白を除いた推奨サイズ幅は`JFormattedTextField#setColumns(8)`で設定した`8`列を掛けて`72px`となる
--- `Ubuntu`環境では`13px*8列=104px`
-- `Font#getStringBounds("BC89FE5A", frc)`で計算される実際の文字列幅は`56.0`(`7px*8文字`?)となるので推奨サイズ幅に余りが発生してしまう
#code{{
// @see JTextField
protected int getColumnWidth() {
if (columnWidth == 0) {
FontMetrics metrics = getFontMetrics(getFont());
columnWidth = metrics.charWidth('m');
}
return columnWidth;
}
public Dimension getPreferredSize() {
Dimension size = super.getPreferredSize();
if (columns != 0) {
Insets insets = getInsets();
size.width = columns * getColumnWidth() + insets.left + insets.right;
}
return size;
}
}}
- `MONOSPACED`
-- `new Font(Font.MONOSPACED, Font.PLAIN, field1.getFont().getSize())`で作成した等幅フォントを設定し、小文字`m`の幅が`7px`となるので、余白を除いた推奨サイズ幅は`JFormattedTextField#setColumns(8)`で設定した`8`列を掛けて`56px`となる
-- `Font#getStringBounds("BC89FE5A", frc)`で計算される実際の文字列幅は`56.0`(`7px*8文字`?)と推奨サイズ幅と一致するため、キャレット`1px`?分が不足して文字列選択などでスクロールが発生する
- `TRACKING-.011f`
-- `Font`のトラッキングを変更して`-1.1%`字詰めを適用し、文字列幅を`54.944px`と`1px`余裕を持たせるよう設定
-- `Java 17`環境では`1px`の余裕では足りず`-2%`字詰めして`2px`余裕がないとスクロールが発生してしまう?
- `PreferredSize+1`
-- `JFormattedTextField#getPreferredSize()`をオーバーライドして余白を除く推奨サイズ幅をプラス`1px`した値となるよう設定
-- `Java 17`環境では`1px`の余裕では足りず`2px`余裕がないとスクロールが発生してしまう?
- `Columns+1`
-- `JFormattedTextField#setColumns(8+1)`と列を`1`文字分増加してスクロールの発生を防ぐよう設定
-- [[JColorChooserのRGB色選択パネル内に表示される16進数カラーコードにAlpha値を追加する>Swing/ColorChooserRgbaHexCode]]のように`16`進数カラーコードを表示する`JFormattedTextField`をオーバーライドしたり、推奨サイズを参照しないレイアウトマネージャを使用することが難しい場合は`JFormattedTextField#setColumns(...)`で列数を`1`文字分増加する方法がスクロールの発生を防ぐ最も手軽な回避方法かもしれない
* Reference [#reference]
- [[JComboBoxなどの幅をカラム数で指定>Swing/SetColumns]]
- [[Fontから文字列の境界を取得する>Swing/StringBounds]]
- [[Fontにトラッキングを設定して文字列幅を詰めて描画する>Swing/Tracking]]
- [[JPasswordFieldでPINコード入力欄を作成する>Swing/PinCodeInputField]]
* Comment [#comment]
#comment
#comment