How to add JCheckBox objects to a JComboBox
Hello,
I want to find a way to add JCheckBox objects to the drop-down list in a JComboBox. When I expand my JComboBox, I want to be able to see my JCheckBox objects and select/deselect them. Here's my SSCCE. Apart from this, I have also tried using a JPopupMenu to put the JCheckBoxes in and add the JPopupMenu to JComboBox. I have also tried adding the JCheckBoxes directly to JComboBox, but neither has worked.
Please advice!
import java.awt.Component;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JComboBox;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
publicclass MyComboBoxTestextends JComboBox
{
/**
* @param args
*/
JComboBox myComboBox;
public MyComboBoxTest()
{
myComboBox =new JComboBox();
}
publicstaticvoid main(String[] args){
JFrame frame =new JFrame("My ComboBox");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setSize(150, 60);
frame.setLocation(300, 300);
final MyComboBoxTest myComboBox =new MyComboBoxTest();
JMenuBar menuBar =new JMenuBar();
JMenu menu =new JMenu();
frame.getContentPane().add(myComboBox);
myComboBox.add(menuBar);
menuBar.add(menu);
menu.add(new JCheckBox("Item1",false));
frame.setVisible(true);
myComboBox.setRenderer(new DefaultListCellRenderer()
{
public Component getListCellRendererComponent(JList list, Object value,
int index,boolean isSelected,boolean cellHasFocus)
{
System.out.println("Inside Renderer");
Component comp = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
return comp;
}
});
}
}
# 2
> Anyone?!?!?!?!
You know, patience is virtue.
Download IconedCellRenderer from this site, http://www.geocities.com/icewalker2g/downloads/IconedCellRenderer.java Or visit the main page http://www.geocities.com/icewalker2g for other useful classes.
I have tweaked the IconedCellRenderer code just enough to work with your JComboBox (it was designed for JLists) so a little more tweaking may have to be done to get it to work perfectly.
import java.awt.Component;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JComboBox;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
public class MyComboBoxTest extends JComboBox
{
/**
* @param args
*/
JComboBox myComboBox;
public MyComboBoxTest()
{
myComboBox = new JComboBox();
}
public static void main(String[] args) {
final MyComboBoxTest myComboBox = new MyComboBoxTest();
for(int i = 0; i < 5; i++) {
myComboBox.addItem("Item " + i);
}
JMenuBar menubar = new JMenuBar();
JMenu menu = new JMenu();
//myComboBox.add(menuBar);
menubar.add(menu);
menu.add(new JCheckBox("Item1",false));
JFrame frame = new JFrame("My ComboBox");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setSize(150, 60);
frame.setLocation(300, 300);
frame.setJMenuBar( menubar );
frame.getContentPane().add(myComboBox);
frame.setVisible(true);
myComboBox.setRenderer( IconedCellRenderer.getCheckBoxRendererInstance() );
/*myComboBox.setRenderer(new DefaultListCellRenderer()
{
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus)
{
System.out.println("Inside Renderer");
Component comp = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
return comp;
}
});*/
}
}
# 3
Hello Ice! Thanks for your help.
I will be able to use your solution once I have the JAR file that recognizes EmptyIcon class. Right now, my code does not understand EmptyIcon() on IconCellRenderer. I've been looking for the jar file, but I'm not sure where to get it. The package for EmptyIcon is org.jdesktop.swingx.icon.EmptyIcon
Could you please get back to me at your earliest convenience?
Thanks!
Message was edited by:
programmer_girl
# 4
Hi, sorry for the frequent posts. My problem is actually solved :) Thanks for all your help! See you next time.
# 5
> Could you please get back to me at your earliest convenience?
Saw your post earlier but was on the move so could not put a reply toegther (almost did).
Just so you know, the EmptyIcon class used is not the one provided by the jdesktop package but my own simple implementation to use whenever I want a space the size of an Icon (usually in JMenuItems). here is the code
import java.awt.Component;
import java.awt.Graphics;
import javax.swing.Icon;
public class EmptyIcon implements Icon {
int width = 16, height = 16;
public EmptyIcon() {
setSize(16,16);
}
public EmptyIcon(int width, int height) {
setSize(width, height);
}
public void setSize(int width, int height) {
this.width = width;
this.height = height;
}
public int getIconWidth() {
return width;
}
public int getIconHeight() {
return height;
}
public void paintIcon(Component c, Graphics g, int x, int y) {
//g.setColor(c.getBackground());
//g.fillRect(x, y, getIconWidth(), getIconHeight() );
}
}
Could you also just let the community know how exactly you are solving your problem? Have you managed to come up with a custom renderer that uses a JCheckBox or you are using the above solution provided?
ICE
# 6
Hello,
Yeah I didn't end up using the swingx EmptyIcon either, I wrote my own, similar to yours and called it MyEmptyIcon. And yes, I did use your IconedCellRenderer implementation. Now I got one problem tho, I want the comboBox to show the word "Items" by default, but when I do the following line,
myComboBox.getModel().setSelectedItem("Items");
Items will be shown with a checkBox next to it, as well. So I'm trying to make changes to the getListCellRenderer() method or the IconCellRenderer(icon) constructor to make it go away. Do you have any suggestions?
# 7
did you try
myComboBox.setSelectedIndex(0);
# 8
The JComboBox renders the non-list display when the index is equal to -1, hence you'd have to put some simple code your getListCellRenderer method to return a simple lable when the index == -1
Below is a code snippet with the correction. See the bottom section with the comment
if(useIconBackground == false) {
if(isSelected)
iconLabel.setIcon(selIcon);
else
iconLabel.setIcon(icon);
if(useCheckBoxAsIcon()) {
if(selState == null) {
updateSelectionStateTrackers(list);
}
if(selStateHandler == null) {
list.addMouseListener( selStateHandler = new SelectionStateHandler(list) );
}
try {
box.setSelected( selState[index] );
} catch(Exception e) {}
}
if( shdPaintDivider() ) {
//if(index < theList.getModel().getSize() - 1 ) {
noback.setBorder( getBorder() );
setBorder( new EmptyBorder(1,1,1,1) );
//} else {
// noback.get
//}
}
// this should cause a JComboBox to paint the Label instead
// of the check box + label combination
if(index == -1) {
JLabel label = new JLabel( this.getText() );
if(iconLabel.getIcon() != null ) {
label.setIcon( iconLabel.getIcon() ); // maybe removed if icon not required
}
return label;
}
return noback;
}
I have also uploaded the fully updated code to my site. It also now includes EmptyIcon as an inner class for easy compilation. Added features are the ability to display hyperlink like items in the list, with hover text underline effects. This is still being tested so the code might not run perfectly. To use that, create the renderer call the method setDisplayItemsAsLinks(true) to enable hyperlink item display. It only unfortunate the code is not well documented.
ICE
# 9
Thank you ICE!!!!! Problem solved :)
# 10
Ice, do you have any idea how I can draw a line underneath my items?
Right now, when I set a MatteBorder in the getListCellRendererComponent method, it only draw under the text and not the JCheckBox. I know why this is the case, but I need the line to cover underneath the JCheckBox as well.
Please let me know.
# 11
ok, here's my updated code. If you can please take a look at it, you'll see what I'm talking about regarding the MatteBorder. It doesn't cover under the JCheckBox. I've tried calling paintComponent(Graphics g) where the code creates the new JCheckBox in IconedCellRenderer, but when it draws a line under the box, the box itself disappears.
Please help me out!
/*MyComboBoxTest.java*/
import javax.swing.JFrame;
import javax.swing.JComboBox;
import java.awt.Dimension;
public class MyComboBoxTest extends JComboBox
{
JComboBox myComboBox;
public MyComboBoxTest()
{
myComboBox = new JComboBox();
}
public static void main(String[] args) {
final MyComboBoxTest myComboBox = new MyComboBoxTest();
//Add Items to myComboBox
myComboBox.getModel().setSelectedItem("Items");
myComboBox.insertItemAt("Select All", 0);
myComboBox.insertItemAt("Item1",1);
myComboBox.insertItemAt("Item2",2);
myComboBox.insertItemAt("Item3",3);
myComboBox.insertItemAt("Item4",4);
myComboBox.insertItemAt("Item5",5);
//Add myComboBox to JFrame
JFrame frame = new JFrame("My ComboBox");
myComboBox.setPreferredSize(new Dimension(140,20));
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setSize(150, 60);
frame.setLocation(300, 300);
frame.getContentPane().add(myComboBox);
frame.setVisible(true);
myComboBox.setRenderer( IconedCellRenderer.getCheckBoxRendererInstance() );
}
}
And Here in IconedCellRenderer, is where I'm trying to paint under JCheckBox
Inside method, createNoBackgroundPanel()
if(useCheckBoxAsIcon()) {
box = new JCheckBox()
{
public void paintComponent(Graphics g)
{
g.drawLine(0,20,20,20);
}
};
box.setOpaque(false);
noback.add( box, BorderLayout.WEST );
rect = box.getBounds();
} else {
noback.add( iconLabel, BorderLayout.WEST );
}
# 12
IconedCellRenderer is already designed to take care of that to some extent. It has a setPaintDivider method which you can use.
IconedCellRenderer renderer = IconedCellRenderer.getCheckBoxRendererInstance();
renderer.setPaintDivider(true);
// you can change the divider color by setting the hyperlink color
// this implementation will definately change. Was done for color
// consistency when using hyperlink display
renderer.setLinkColor( Color.red );
// you can also use an image as a divider
// uncomment and supply image.
//renderer.setDividerImage( new ImageIcon("image.gif") );
myComboBox.setRenderer( renderer );
ICE
# 13
Thank you! Ice, you're truly a life saver!