Skip to Main Content

Java SE (Java Platform, Standard Edition)

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

JComboBox and ListCellRenderer

843805Jan 27 2006 — edited Jan 27 2006
Hi all!

I have created a JComboBox that can display one or more columns in its popup in order to get nice looking straight columns. It also widens the popup to be able to show long items. It can also be made editable.

My problem is that with certain look-and-feels, the selected value in the combo can not be seen while the combo has focus. In our application the user can choose from a variety of third-party skins. In some of them the combo background color is grey, and there I see that the text is shown, but it is white. So, in skins where the background color is white the text is also white and therefore appears to not be shown.

I have tried to strip the code as much as I can without removing the essential functionality. I appologise for the lengthy code snippet, but I have noticed that it is very easy to destroy the look in one situation while trying to get it right for another when tampering with the ListCellRenderer.

This example uses the WindowsLookAndFeel, and what I would like is to be able to make the text (in the third combo) any other color that white when the combo has focus. The best would be if it looked just like the normal JComboBox (the first combo), but at this point I'm desperate and will take anything that at least shows the text. I have tried to return a JTextField instead of a JLabel in the renderer, but there are some drawbacks to that, and I would really like to have a JLabel if possible.

Can anyone please help me!
/Sara
import java.awt.*;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.plaf.basic.*;

/* 
 * @author Sara Olsson 
 */
public class MultiColumnJComboBox 
	extends JComboBox
	implements ListCellRenderer
	{
		int _noOfCols = 1;
		List _colList = new ArrayList();
	 	JPanel _panel;
	    Font _font;
	    protected static Border _noFocusBorder;
		boolean _hideCol0All = true;
	    boolean _hideCol1All = true;
	    boolean _widenPopup = true;
	    boolean _editable = false;
	    String _editedItem = " ";
	    private static final int _cellPadding = 3;
	    
	    
	    public static void main(String[] args)
		{
			try {
				UIManager.LookAndFeelInfo[] info = UIManager.getInstalledLookAndFeels();
				UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
				//UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel");
				//UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
			} catch (Exception e){
				System.out.println("Could not set Windows look and feel");
			}
			
			JFrame frame = new JFrame();
			SwingUtilities.updateComponentTreeUI(frame);
			
			JComboBox jCombo = new JComboBox();
			Dimension dim = new Dimension(80, (int)jCombo.getPreferredSize().getHeight());
			jCombo.setPreferredSize(dim);
			MultiColumnJComboBox mCombo = new MultiColumnJComboBox(2, true);
			mCombo.setPreferredSize(dim);
			MultiColumnJComboBox m2Combo = new MultiColumnJComboBox(2, false);
			m2Combo.setPreferredSize(dim);
			m2Combo.hideColumn(0, true, false);
			
			String[] kod = {"", "100", "5", "4500", "300", "10"};
			String[] text = {"", "text1", "text2", "text3-really long text-", "text4", "text5"};
			for (int i=0; i<5; i++) {
				jCombo.addItem(new String(kod[i] + " " + text));
mCombo.addItem(kod[i], text[i]);
m2Combo.addItem(kod[i], text[i]);
}

JPanel panel = new JPanel();
panel.add(new JLabel("JComboBox: "));
panel.add(jCombo);
panel.add(new JLabel("MulitColumn(editable): "));
panel.add(mCombo);
panel.add(new JLabel("MulitColumn(not editable): "));
panel.add(m2Combo);

frame.getContentPane().add(panel);
frame.pack();
frame.show();
}

public MultiColumnJComboBox(int noOfCols, boolean editable)
{
_editable = editable;
setEditable(editable);
_noOfCols = noOfCols;
_font = this.getFont();
_noFocusBorder = new EmptyBorder(1,1,1,1);
_panel = new JPanel(new GridBagLayout());
for (int i=0; i<_noOfCols; i++) {
_colList.add(new ComboColumn());
}
setRenderer(this);
setEditor(new MyEditor());
}

public void setEnabled(boolean enabled)
{
_editedItem = " ";
repaint();
super.setEnabled(enabled);
}

public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected,
boolean cellHasFocus)
{
Object obj = getEditor().getItem();
if (obj instanceof String)
_editedItem = ((String)obj).trim();
else
_editedItem = " ";

if (value == null)
value = "";
JComboBox templateCombo = new JComboBox();
if (_font == null)
_font = list.getFont();
if (value instanceof List) {
List valueList = (List)value;
String str = parseValues(valueList).trim();
if (_editable && (str.equals(_editedItem) || str.equals("")) && isSelected) {
this.setEditable(true);
getEditor().setItem(_editedItem);
}
JLabel label;
if (index == -1) {
this.setToolTipText(getToolTipText(valueList));
if (_editable && str.trim().equals("")) {
str = _editedItem;
}
if ((str.trim().equals("") || str.trim().equals(_editedItem)) && _editable) {
setEditable(true);
getEditor().setItem(_editedItem);
}
JLabel l = new JLabel(str);
this.setForeground(Color.RED);
l.setForeground(Color.PINK);
return l;
}
_panel.removeAll();
StringBuffer strBuf = new StringBuffer();
for(int i=0; i<_colList.size(); i++) {
ComboColumn col = (ComboColumn)_colList.get(i);
if (col._showInPopup) {
label = col._label;
label.setFont(_font);
String val = "";
if (i < valueList.size() && valueList.get(i) != null)
val = ((String)valueList.get(i)).trim();
if (val.equals(""))
label.setText(" ");
else
label.setText(val.trim());
Dimension d = label.getPreferredSize();
d.width = col.getWidth();
label.setSize(d);
label.setPreferredSize(d);
_panel.setBackground(templateCombo.getBackground());
label.setForeground(templateCombo.getForeground());
if (isSelected) {
_panel.setBackground(list.getSelectionBackground());
label.setForeground(list.getSelectionForeground());
}
label.setEnabled(isEnabled());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(1,1,1,1);
gbc.weightx = 1.0;
gbc.fill = GridBagConstraints.HORIZONTAL;
if (i==_colList.size()-1)
gbc.gridwidth = GridBagConstraints.REMAINDER;
_panel.add(label, gbc);
}
}
_panel.setBorder(cellHasFocus ? UIManager
.getBorder("List.focusCellHighlightBorder") : _noFocusBorder);

return _panel;
}
else {
List valList = new ArrayList();
valList.add(value.toString());
return getListCellRendererComponent(list, valList, index, isSelected, cellHasFocus);
}
}

private String parseValues(List valueList)
{
StringBuffer strBuf = new StringBuffer();
boolean first = true;
for (int i=0; i<_colList.size(); i++) {
ComboColumn col = (ComboColumn)_colList.get(i);
if (col._showInSelected) {
if (!first)
strBuf.append(" ");
if (i < valueList.size() && valueList.get(i) != null)
strBuf.append(((String)valueList.get(i)).trim());
first = false;
}
}
return strBuf.toString();
}

private String getToolTipText(List values)
{
StringBuffer buf = new StringBuffer();
Iterator iter = values.iterator();
while (iter.hasNext()) {
String str = (String)iter.next();
if (str != null)
buf.append(str.trim());
if (iter.hasNext())
buf.append(" ");
}
return buf.toString();
}


public void addItem(List strList)
{
for (int i=0; i<strList.size(); i++) {
String str = (String)strList.get(i);
if (i<_colList.size()) {
ComboColumn col = (ComboColumn)_colList.get(i);
JLabel template = new JLabel(str.trim());
template.setFont(_font);
col.setPreferredWidth(template.getPreferredSize().width + _cellPadding);
}
}
super.addItem(strList);
}

public void addItem(String col1, String col2)
{
List list = new ArrayList();
list.add(col1);
list.add(col2);
addItem(list);
}

public void addItem(Object obj)
{
List list = new ArrayList();
list.add(obj);
if (obj instanceof List)
list = (List)obj;
addItem(list);
}

public void hideColumn(int col, boolean hide, boolean all)
{
if (col < _colList.size()) {
ComboColumn column = (ComboColumn)_colList.get(col);
column._showInSelected = !hide;
column._showInPopup = !hide;
if (hide && !all)
column._showInPopup = true;
}
}


//Anv�nds f�r att visa bred popup
public void updateUI() {
super.updateUI();
resizeComboPopup();
}

//Anv�nds f�r att visa bred popup
public void firePopupMenuWillBecomeVisible() {
resizeComboPopup();
super.firePopupMenuWillBecomeVisible();
}

//Anv�nds f�r att visa bred popup
private void resizeComboPopup()
{
if (_widenPopup) {
BasicComboPopup popup = (BasicComboPopup)getUI().getAccessibleChild(this,0);
//Popup
if(popup==null)
return;
int comboSize = getWidth();
int newSize = (int)getPreferredSize().getWidth();
for(int i=0; i<getItemCount(); i++){
if(newSize < _panel.getPreferredSize().getWidth())
newSize = (int)_panel.getPreferredSize().getWidth();
}
//Se till att popup'en inte blir smalare �n combon.
if (newSize < comboSize)
newSize = comboSize;
Component comp = popup.getComponent(0);
JScrollPane scrollpane=null;
int offset=0;
if(comp instanceof JScrollPane) {
scrollpane = (JScrollPane)comp;
if(scrollpane.getVerticalScrollBar().isVisible())
offset += scrollpane.getVerticalScrollBar().getWidth();
}
int height = getPopupHeight();
//popup.setPreferredSize(new Dimension(newSize+offset,popup.getPreferredSize().height));
popup.setPreferredSize(new Dimension(newSize+offset, height));
popup.setLayout(new BorderLayout());
popup.add(comp,BorderLayout.CENTER);
}
}

//Inte 100%, men den duger tills vidare.
private int getPopupHeight()
{
int rows = getMaximumRowCount();
if (getItemCount() < rows)
rows = getItemCount();
JPanel panel = new JPanel(new GridBagLayout());
JLabel label = new JLabel("Test");
label.setFont(_font);
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(1,1,1,1);
gbc.weightx = 1.0;
gbc.fill = GridBagConstraints.HORIZONTAL;
panel.add(label, gbc);
JScrollPane pane = new JScrollPane(panel);
return pane.getPreferredSize().height * rows;
}

private class ComboColumn
{
public JLabel _label;
public int _preferredWidth = -1;
public int _fixedWidth = -1;
public boolean _showInPopup = true;
public boolean _showInSelected = true;

public ComboColumn()
{
_label = new JLabel();
label.setFont(font);
preferredWidth = (int)label.getPreferredSize().getWidth();
}

public void setPreferredWidth(int width)
{
if (_preferredWidth < width)
_preferredWidth = width;
}


public int getWidth()
{
if (_fixedWidth != -1)
return _fixedWidth;
return _preferredWidth;
}
}

private class MyEditor
extends BasicComboBoxEditor
{
public Component getEditorComponent()
{
JComponent textField = (JTextField)super.getEditorComponent();
/*
try {
MaskFormatter format = new MaskFormatter("***");
textField = new JFormattedTextField(format);
}
catch(Exception e) {
return super.getEditorComponent();
}
*/
return textField;
}

public void setItem(Object anObject)
{

if (anObject != null && anObject.toString().equals("[, ]"))
anObject = " ";
if (anObject instanceof List) {
List list = (List)anObject;
if (list.size() > 0)
anObject = list.get(0);
}
super.setItem(anObject);
}

public Object getItem()
{
Object obj = super.getItem();
if (obj instanceof List) {
List list = (List)obj;
if (list.size() > 0) {
setItem(list.get(0));
return list.get(0);
}
}
return obj;
}
}
}
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Feb 24 2006
Added on Jan 27 2006
4 comments
640 views