JButtonなどの高さを変更せずに幅を指定
Total: 32116
, Today: 2
, Yesterday: 3
Posted by aterai at
Last-modified:
概要
高さはデフォルトのまま幅だけを指定して、JButton
、JComboBox
、JTextField
などのサイズを変更します。
Screenshot
Advertisement
サンプルコード
private static JComponent createRightAlignButtonBox2(
List<JButton> list, final int buttonWidth, int gap) {
JComponent box = new JPanel() {
@Override public void updateUI() {
for (JButton b : list) {
b.setPreferredSize(null);
}
super.updateUI();
EventQueue.invokeLater(new Runnable() {
@Override public void run() {
int maxHeight = list.stream()
.map(b -> b.getPreferredSize().height)
.reduce(0, Integer::max);
Dimension d = new Dimension(buttonWidth, maxHeight);
for (JButton b : list) {
b.setPreferredSize(d);
}
revalidate();
}
});
}
};
box.setLayout(new BoxLayout(box, BoxLayout.X_AXIS));
box.add(Box.createHorizontalGlue());
for (JButton b : list) {
box.add(b);
box.add(Box.createHorizontalStrut(gap));
}
box.setBorder(BorderFactory.createEmptyBorder(gap, 0, gap, 0));
return box;
}
View in GitHub: Java, Kotlin解説
上記のサンプルでは、JButton
の高さはデフォルト、幅をその文字列によらずに一定、配置は右寄せで水平にしたい場合のレイアウト方法をテストしています。
Default
BoxLayout
でBox.createHorizontalGlue()
を使用して右寄せJButton
の幅はその文字列の長さに依存
getPreferredSize
Box
を使用して右寄せJButton
の幅はJButton#setPreferredSize(...)
で固定幅を設定JButton
の高さはJButton#getPreferredSize()
で取得したサイズの高さを使用LookAndFeel
を変更するとJButton
の高さが変化するので、その場合はJButton#updateUI()
をオーバーライドしてJButton#setPreferredSize(...)
を使用する必要がある
SpringLayout
+Box
- SpringLayoutの使用
SpringLayout
で幅指定、BoxLayout
で右寄せSpringLayout.Constraints
でJButton
の固定幅を指定- 親パネルの幅も
SpringLayout.Constraints
で固定し、Box
で入れ子にして右寄せ LookAndFeel
を変更するとJButton
の高さが変化するので、その場合はJComponent#getPreferredSize(...)
をオーバーライドして親パネルの高さを更新する必要がある
SpringLayout
- SpringLayoutの使用
SpringLayout
を使用して右寄せSpringLayout.Constraints
でJButton
の幅を固定LookAndFeel
を変更するとJButton
の高さが変化するので、その場合はJComponent#getPreferredSize(...)
をオーバーライドして親パネルの高さを更新する必要がある
GridLayout
+Box
GridLayout
で幅指定、BoxLayout
で右寄せGridLayout
ですべてのJButton
のサイズを同じにするBox
で入れ子にして右寄せ- 幅が最大の
JButton
のテキストが変更されると、親のBox
の幅が変化してしまう
以下、setPreferredSize()
を使用する際の補足、注意点です。
JButton
のUI
がフォントサイズや文字列の長さから決めたデフォルトサイズをgetPreferredSize()
で取得しています。高さはそのまま利用し、幅だけ一定の値を設定して、新たなデフォルトサイズを作成し、setPreferredSize()
しています。これで次からgetPreferredSize()
で返ってくる値は、どちらのボタンでも全く同じになります。
このsetPreferredSize(...)
で設定したサイズは、LookAndFeel
を変更しても残ってしまう(DimensionUIResource
を使用しても効果がない)ため、LookAndFeel
がデフォルトで使用する高さを取得したい場合は、updateUI()
をオーバーライドして、一旦JButton#setPreferredSize(null);
を設定して幅を変更した推奨サイズをクリアしてから、super.updateUI();
で推奨サイズを更新し、その後で固定幅、LookAndFeel
デフォルトの高さをsetPreferredSize(...)
で設定し直す必要があります。
getPreferredSize()
で得られる値を使用するかどうかは、レイアウトマネージャーによって異なりますが、水平方向にコンポーネントを並べるBoxLayout
の場合は以下のようになるため、パネルをリサイズしても、ボタンのサイズはどちらも同じで変化しません。
- 幅: 推奨サイズ(
getPreferredSize
メソッド)から取得した値 - 高さ: 各コンポーネントの推奨サイズ(
getPreferredSize
メソッド)で得られた中からもっとも大きな値- 上記のサンプルで
button1.setPreferredSize(new Dimension(100, 0));
としても結果は同じ
- 上記のサンプルで
例えば、各ボタンを格納した親フレームをpack()
する前にJButton#getPreferredSize()
ではなく、JButton#getSize()
でサイズを取得すると、[width=0,height=0]
が帰ってきます。コンポーネントが表示されている場合、getSize()
で得られるサイズは、その実際に表示されているサイズ(レイアウトマネージャーが決定する)になります。
以下はJLabel
をgetPreferredSize()
した場合の例です。初期状態(preferredSize
がnull
)の場合は、JLabel
のUI
がサイズを計算しています。
JLabel l = new JLabel();
l.setText("a"); //preferredSizeがnullの場合、UIがサイズを計算
// l.getPreferredSize() -> Dimension[width=6, height=13]
l.setText("aaaa"); //JLabelの場合、Fontサイズと文字列の長さなどで決まる
// l.getPreferredSize() -> Dimension[width=24, height=13]
l.setText("<html>aa<br>aa");
// l.getPreferredSize() -> Dimension[width=12, height=26]
l.setPreferredSize(new Dimension(10, 10)); //preferredSizeを設定した場合
// l.getPreferredSize() -> Dimension[width=10, height=10]
l.setPreferredSize(null); //preferredSizeをnullに戻した場合
// l.getPreferredSize() -> Dimension[width=12, height=26]
参考リンク
- JComboBoxなどの幅をカラム数で指定
JComboBox
、JTextField
などのコンポーネントでは、カラム数による幅の指定が可能JDK 1.5.0
: カラム数で幅を指定すると、コンポーネントによってサイズや余白などが微妙に異なるJDK 1.6.0
以上:LookAndFeel
が同じなら、カラム数での幅指定で、どのコンポーネントでもほぼ同じサイズになる
- SpringLayoutの使用
- Santhosh Kumar's Weblog
- 専用のレイアウトマネージャーを作成するサンプル
- JOptionPaneで使用するボタンのサイズを揃える