JComboBoxのFocusBorderの対象を内部のアイテムではなくJComboBox自体に変更する
Total: 2544, Today: 1, Yesterday: 0
Posted by aterai at
Last-modified:
Summary
WindowsLookAndFeelでJComboBoxの内部アイテムに適用される点線のFocusBorderを非表示にし、代替としてJComboBox自体に実線のFocusBorderを表示します。
Screenshot

Advertisement
Source Code Examples
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, KotlinDescription
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();
}
}
});
Reference
- JTreeのノードの文字列に余白を追加
JTreeの場合で、フォーカスの点線と文字列の間に余白を追加