JButtonなどの高さを変更せずに幅を指定
Total: 33188, Today: 1, Yesterday: 7
Posted by aterai at
Last-modified:
Summary
高さはデフォルトのまま幅だけを指定して、JButton、JComboBox、JTextFieldなどのサイズを変更します。
Screenshot

Advertisement
Source Code Examples
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, KotlinDescription
上記のサンプルでは、JButtonの高さはデフォルト、幅をその文字列によらずに一定、配置は右寄せで水平にしたい場合のレイアウト方法をテストしています。
DefaultBoxLayoutでBox.createHorizontalGlue()を使用して右寄せJButtonの幅はその文字列の長さに依存
getPreferredSizeBoxを使用して右寄せ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+BoxGridLayoutで幅指定、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]
Reference
- JComboBoxなどの幅をカラム数で指定
JComboBox、JTextFieldなどのコンポーネントでは、カラム数による幅の指定が可能JDK 1.5.0: カラム数で幅を指定すると、コンポーネントによってサイズや余白などが微妙に異なるJDK 1.6.0以上:LookAndFeelが同じなら、カラム数での幅指定で、どのコンポーネントでもほぼ同じサイズになる
- SpringLayoutの使用
- Santhosh Kumar's Weblog
- 専用のレイアウトマネージャーを作成するサンプル
- JOptionPaneで使用するボタンのサイズを揃える