Swing/FileChooserBottomAccessory のバックアップ(No.6)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - 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?export=view&id=1Nyb4wo_ryaaCsJEgpGBxbIlYazx3FQVFfw
概要
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)