MetalLookAndFeelでJFileChooserの下部にコンポーネントを追加する
Total: 3578
, Today: 1
, Yesterday: 0
Posted by aterai at
Last-modified:
概要
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)