Swing/ComboBoxFocusBorder のバックアップ(No.4)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/ComboBoxFocusBorder へ行く。
- 1 (2018-06-04 (月) 15:50:16)
- 2 (2018-06-04 (月) 17:51:21)
- 3 (2020-05-22 (金) 17:43:43)
- 4 (2021-11-11 (木) 01:11:14)
- category: swing folder: ComboBoxFocusBorder title: JComboBoxのFocusBorderの対象を内部のアイテムではなくJComboBox自体に変更する tags: [JComboBox, Focus, Border, WindowsLookAndFeel] author: aterai pubdate: 2018-06-04T15:29:53+09:00 description: WindowsLookAndFeelでJComboBoxの内部アイテムに適用される点線のFocusBorderを非表示にし、代替としてJComboBox自体に実線のFocusBorderを表示します。 image: https://drive.google.com/uc?id=1c5v18Ay9IHqlvUQYoK72CBW4ln2OS5QXxQ
概要
WindowsLookAndFeel
でJComboBox
の内部アイテムに適用される点線のFocusBorder
を非表示にし、代替としてJComboBox
自体に実線のFocusBorder
を表示します。
Screenshot
Advertisement
サンプルコード
JComboBox<String> combo3 = new JComboBox<String>(model) {
@Override public void updateUI() {
setRenderer(null);
super.updateUI();
if (isWindowsLnF()) {
setRenderer(new DefaultListCellRenderer() {
@Override public Component getListCellRendererComponent(
JList<?> list, Object value, int index,
boolean isSelected, boolean cellHasFocus) {
JLabel l = (JLabel) super.getListCellRendererComponent(
list, value, index, isSelected, cellHasFocus);
if (index < 0) {
l.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
}
return l;
}
});
}
}
@Override protected void paintBorder(Graphics g) {
super.paintBorder(g);
if (isFocusOwner() && !isPopupVisible() && isWindowsLnF()) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setPaint(Color.DARK_GRAY);
g2.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
g2.dispose();
}
}
private boolean isWindowsLnF() {
return getUI().getClass().getName().contains("WindowsComboBoxUI");
}
};
View in GitHub: Java, Kotlin解説
default
- デフォルトの
WindowsLookAndFeel
で編集不可のJComboBox
にフォーカスがある場合、内部アイテム(セルレンダラー内部)に点線のFocusBorder
が表示される - 点線と文字列の間隔が近く?若干うるさい感じがする
- デフォルトの
setFocusable(false)
JComboBox#setFocusable(false)
で点線は非表示になるが、フォーカスが当たらなくなる
setRenderer(...)
DefaultListCellRenderer#getListCellRendererComponent(...)
メソッドをオーバーライドし、インデックスが0
以下(JComboBox
本体での内部アイテムの描画)の場合は空のBorder
を使用することで点線を非表示に設定WindowsLookAndFeel
以外では、内部アイテムにFocusBorder
は付かないのでこのセルレンダラーは適用しない- フォーカスが当たっているかどうかが判別しづらくなる
paintBorder(...)
- 上記と同様のフォーカスがあっても点線を非表示にするセルレンダラーを適用
JComboBox#paintBorder(...)
をオーバーライドして別途JComboBox
本体にFocusBorder
を描画
WindowsLookAndFeel
でもUIManager.put("ComboBox.border", ...)
でJComboBox
本体のBorder
を変更することは可能だが、内部アイテムに適用されるBorder
を変更する方法は現状では存在しない?
UIManager.put("ComboBox.border", new LineBorder(Color.GRAY.brighter()) {
@Override public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
super.paintBorder(c, g, x, y, width, height);
if (c.isFocusOwner()) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setPaint(Color.DARK_GRAY);
g2.drawRect(x, y, width - 1, height - 1);
g2.dispose();
}
}
});
参考リンク
- JTreeのノードの文字列に余白を追加
JTree
の場合で、フォーカスの点線と文字列の間に余白を追加