Swing/FileChooserBottomAccessory のバックアップ(No.10)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/FileChooserBottomAccessory へ行く。
- category: swing
folder: FileChooserBottomAccessory
title: MetalLookAndFeelでJFileChooserの下部にコンポーネントを追加する
tags: [JFileChooser, MetalLookAndFeel]
author: aterai
pubdate: 2017-08-14T15:32:42+09:00
description: MetalLookAndFeelを適用しているJFileChooserのファイルフィルタとボタンパネルの間にJComboBoxのような横長のコンポーネントを追加します。
image: https://drive.google.com/uc?id=1Nyb4wo_ryaaCsJEgpGBxbIlYazx3FQVFfw
hreflang:
href: https://java-swing-tips.blogspot.com/2017/09/add-jcombobox-that-selects-encoding-at.html lang: en
概要
MetalLookAndFeel
を適用しているJFileChooser
のファイルフィルタとボタンパネルの間にJComboBox
のような横長のコンポーネントを追加します。
Screenshot
Advertisement
サンプルコード
class EncodingFileChooserUI extends MetalFileChooserUI {
public final JComboBox<String> combo = new JComboBox<>(
new String[] {"UTF-8", "UTF-16", "Shift_JIS", "EUC-JP"});
protected EncodingFileChooserUI(JFileChooser filechooser) {
super(filechooser);
}
@Override public void installComponents(JFileChooser fc) {
super.installComponents(fc);
JPanel bottomPanel = getBottomPanel();
JLabel label = new JLabel("Encoding:") {
@Override public Dimension getPreferredSize() {
return SwingUtils.stream(bottomPanel)
.filter(JLabel.class::isInstance).map(JLabel.class::cast)
.findFirst()
.map(JLabel::getPreferredSize)
.orElse(super.getPreferredSize());
}
};
label.setDisplayedMnemonic('E');
label.setLabelFor(combo);
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.LINE_AXIS));
panel.add(label);
panel.add(combo);
// 0: fileNamePanel
// 1: RigidArea
// 2: filesOfTypePanel
bottomPanel.add(Box.createRigidArea(new Dimension(1, 5)), 3);
bottomPanel.add(panel, 4);
SwingUtils.stream(bottomPanel)
.filter(JLabel.class::isInstance).map(JLabel.class::cast)
.forEach(l -> {
l.setHorizontalAlignment(SwingConstants.RIGHT);
l.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5));
});
}
}
View in GitHub: Java, Kotlin解説
JFileChooser#setAccessory(JComponent)
を使用するとJFileChooser
の右側にコンポーネントが追加されるので、横長のコンポーネントを追加するとJFileChooser
全体の幅が広がってしまうBasicFileChooserUI#getBottomPanel()
メソッドでファイル名入力欄、ファイルフィルタ、ボタンなどを格納している下部パネルを取得し、「ファイルのタイプ(T
)」パネルとボタンパネルの間にJComboBox
のような横長のコンポーネントを設定した別パネルを追加MetalFileChooserUI
の場合、2
番目のfilesOfTypePanel
の直後になるようbottomPanel.add(Box.createRigidArea(vstrut5), 3); bottomPanel.add(encodingPanel, 4)
で追加BasicFileChooserUI#getBottomPanel()
で取得できるJPanel
内のレイアウトは、LookAndFeel
ごとに大きく異なるため同じ方法は使用できない- 例えば
WindowsLookAndFeel
ではBoxLayout.LINE_AXIS
、MetalLookAndFeel
ではBoxLayout.Y_AXIS
- 例えば
MetalFileChooserUI
ではJLabel
を継承するAlignedLabel
で最も長い文字列幅から推奨サイズを揃えているが、private
のためこのサンプルでは使用できない- Containerの子Componentを再帰的にすべて取得するでラベルを検索して推奨サイズを取得しているが、もし
Encoding:
がこの最も長い文字列幅より長い場合は末尾が省略されてしまう
- Containerの子Componentを再帰的にすべて取得するでラベルを検索して推奨サイズを取得しているが、もし
JFileChooser#updateUI()
メソッドをオーバーライドしてsuper.updateUI(); setUI(new EncodingFileChooserUI(this));
などを実行した場合、AcceptAll
ファイルフィルタが重複追加されてしまうsetUI(...)
の後でJFileChooser#resetChoosableFileFilters()
を実行するか、super.updateUI()
を実行しないことで回避可能- 個別のファイルフィルタ追加などの設定は
JFileChooser#updateUI()
メソッド内で実施する
- 個別のファイルフィルタ追加などの設定は
参考リンク
- JFileChooserに画像プレビューを追加
- Containerの子Componentを再帰的にすべて取得する
- Container#add(Component, int) (Java Platform SE 8)