java - JComboBox Cell Renderer Fails with Windows Look and Feel -
i writing java application uses local system , feel. in program there listcellrenderer renders colored dot (a custom jcomponment) followed text given object. works fine when using swing's default metal , feel.
however, when use windows , feel, cells rendered correctly in drop-down list, selected item (the 1 displayed when user not in act of selecting different option) renders text , ignores colored dot. if change renderer set font, proper font observed in both drop down , selected item, know cell renderer being used, @ least in part.
i've read posts around web different lafs causing problems haven't come across who's discussing particular problem.
in case curious here code:
.
@override public component getlistcellrenderercomponent(jlist<? extends coloreddisplayable> jlist, coloreddisplayable e, int i, boolean isselected, boolean hasfocus) { jpanel cell = new jpanel(new gridbaglayout()); cell.setopaque(false); jlabel label = new jlabel(e.getdisplaystring()); label.setopaque(false); label.setborder(borderfactory.createemptyborder(1, 4, 1, 4)); label.sethorizontalalignment(jlabel.left); color deselectedbackground = cell.getbackground(); color deselectedtextcolor = cell.getforeground(); // layout components // dot gridbagconstraints gbc = new gridbagconstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.insets = insets; gbc.anchor = gridbagconstraints.line_start; gbc.weightx = 0.0f; gbc.fill = gridbagconstraints.none; cell.add(new dot(e.getcolor()), gbc); // label gbc.gridx = 1; gbc.weightx = 1.0f; gbc.fill = gridbagconstraints.horizontal; cell.add(label, gbc); if (isselected){ cell.setopaque(true); cell.setbackground(metallookandfeel.gettexthighlightcolor()); } else { cell.setbackground(deselectedbackground); cell.setforeground(deselectedtextcolor); } return cell; }
also, here's code custom component inc ase wants try out see if i'm doing silly here:
public class dot extends jcomponent { /** size of dot. */ private static final int size = 10; /** size of dot. */ private static final int pad = 4; private static final dimension dim = new dimension(size + pad, size + pad); /** color render dot. */ private final color m_color; /** dot itself. */ private static final ellipse2d.double dot = new ellipse2d.double(pad / 2, pad / 2, size, size); /** * creates dot of specified color. * @param color color make dot. */ public dot(color color) { m_color = color; } @override public void paintcomponent(graphics g) { graphics2d g2d = (graphics2d)g; g2d.setrenderinghint(renderinghints.key_antialiasing, renderinghints.value_antialias_on); g2d.setcolor(m_color); g2d.fill(dot); } @override public dimension getpreferredsize() { return dim; } }
edit: tested on ubuntu 12.04 , cell renderer worked expected there (although jcombobox didn't render outside border if no custom renderer applied).
edit: more , more, seems though there may seteditor method on jcombobox, when not editable, renderer should used javadoc method states:
sets editor used paint , edit selected item in jcombobox field. editor used if receiving jcombobox editable. if not editable, combo box uses renderer paint selected item.
that doesn't appear behavior i'm seeing. must in order have parts of cell renderer observed users of windows laf?
digging this, found windows laf, need set comboboxeditor , set jcombobox editable in order selected cell render properly.
this appears me bug/unintended function specific windows , feel api jcombobox's seteditor method states when not editable, renderer used - , when run in both default metal laf , on ubuntu.
in addition that, wasn't able have editor return new cell each time geteditorcomponent called 1 in listcellrenderer. suppose makes sense.
this website provides example (albeit sort of lackluster one) of how create editor:
the api jcombobox , basiccombobox helpful:
and finally, editor code:
public class coloreddisplayablecomboboxeditor extends basiccomboboxeditor { private coloreddisplayable m_cd = null; private static final insets insets = new insets(3, 1, 3, 1); private final jpanel m_cell; private final jlabel m_label; private final dot m_dot; public coloreddisplayablecomboboxeditor() { // initialize // panel m_cell = new jpanel(new gridbaglayout()); m_cell.setopaque(false); // label m_label = new jlabel(); m_label.setopaque(false); m_label.setborder(borderfactory.createemptyborder(0, 4, 0, 4)); m_label.sethorizontalalignment(jlabel.left); // dot m_dot = new dot(color.black); // layout // dot gridbagconstraints gbc = new gridbagconstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.insets = insets; gbc.anchor = gridbagconstraints.line_start; gbc.weightx = 0.0f; gbc.fill = gridbagconstraints.none; m_cell.add(m_dot, gbc); // label gbc.gridx = 1; gbc.weightx = 1.0f; gbc.fill = gridbagconstraints.horizontal; m_cell.add(m_label, gbc); } @override public component geteditorcomponent() { return m_cell; } @override public object getitem() { system.out.println("getting item."); return m_cd; } @override public void setitem(object item) { system.out.println("setting item."); if (item instanceof coloreddisplayable) { coloreddisplayable cd = (coloreddisplayable)item; if (!cd.equals(m_cd)) { system.out.println("--item set."); m_cd = cd; m_label.settext(m_cd.getdisplaystring()); m_dot.setcolor(m_cd.getcolor()); } } else { throw new illegalargumentexception("parameter item must coloreddisplayable."); } } }
Comments
Post a Comment