Implement JQuery style MultiSelect JComboBox with JCheckBox
Use {@link #getSelectedItems() getSelectedItems} method. to get the selected item list
See http://www.erichynds.com/examples/jquery-ui-multiselect-widget/demos/
for the referenced JQuery implementation.
package combo;
import javax.swing.JFrame;
public class MultiCheckComboTEst extends JFrame{
private static final long serialVersionUID = -3578706354915513446L;
public static void main(String[] args) throws Exception {
MultiCheckComboTEst frame = new MultiCheckComboTEst();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
public MultiCheckComboTEst() throws Exception
{
String[] ids = { "ALL","FX", "IR", "EQ", "BOND" };
MultiCheckComboBox comboBox = new MultiCheckComboBox( ids );
add( comboBox );
}
}
////////////////////////////
package combo;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.plaf.basic.ComboPopup;
/**
* Implement JQuery style MultiSelect JComboBox with JCheckBox
* Use {@link #getSelectedItems() getSelectedItems} method. to get the selected item list
* <p>
* See <a href="http://www.erichynds.com/examples/jquery-ui-multiselect-widget/demos/">Basic Demo</a>
* for the referenced JQuery implementation.
* <p>
* @author pengp2
*
*/
public class MultiCheckComboBox extends JComboBox {
private static final long serialVersionUID = 4735456197188571568L;
private MultiCheckComboModel[] models;
public MultiCheckComboBox(final Object items[]) {
this(items,null);
}
public MultiCheckComboBox(final Object items[],Boolean states[]){
super();
if(items==null){
System.err.println("items cannot be null.");
return;
}
if(states==null){
states = new Boolean[items.length];
Arrays.fill(states, false);
}
if(items.length!=states.length){
System.err.println("Unexpected parameters for MultiCheckComboBox.");
return;
}
models = new MultiCheckComboModel[items.length];
for(int i=0;i<items.length;i++){
models[i] = new MultiCheckComboModel(items[i].toString(),states[i]);
}
setModel(new DefaultComboBoxModel(models));
}
@Override
public void updateUI() {
super.updateUI();
final MultiCheckComboRenderer render = new MultiCheckComboRenderer();
setRenderer(render);
setUI(new MultiCheckComboBoxUI());
addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
MultiCheckComboModel comboModel = (MultiCheckComboModel) MultiCheckComboBox.this.getModel().getSelectedItem();
comboModel.setIsSelected(!comboModel.getIsSelected());
render.getCheckBox().setSelected(comboModel.getIsSelected());
if (comboModel.getId().equalsIgnoreCase("ALL")){
for (int i = 0; i < getItemCount(); i++){
((MultiCheckComboModel)getItemAt(i)).setIsSelected(render.getCheckBox().isSelected());
}
}
int selectedNum = 1;
for (int i = 1; i < getItemCount(); i++){
if(((MultiCheckComboModel)getItemAt(i)).getIsSelected()){
selectedNum++;
}
}
((MultiCheckComboModel)getItemAt(0)).setIsSelected(selectedNum==getItemCount());
getModel().setSelectedItem(selectedNum-1+" selected");
getEditor().getEditorComponent().repaint();
repaint();
((ComboPopup) getUI().getAccessibleChild(MultiCheckComboBox.this, 0)).getList().repaint();
// MultiCheckComboModel[] selected = MultiCheckComboBox.this.getModels();
// for(MultiCheckComboModel selectedO:selected){
// System.out.println("selectedO="+selectedO);
// }
}
});
}
public MultiCheckComboModel[] getSelectedItems() {
return models;
}
}
///////
package combo;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JComponent;
import javax.swing.SwingUtilities;
import javax.swing.plaf.basic.BasicComboPopup;
import javax.swing.plaf.basic.ComboPopup;
import javax.swing.plaf.metal.MetalComboBoxUI;
public class MultiCheckComboBoxUI extends MetalComboBoxUI {
@Override
protected ComboPopup createPopup() {
return new BasicComboPopup(comboBox) {
private static final long serialVersionUID = -1657533899648565541L;
@Override
protected MouseListener createListMouseListener() {
return new MouseListener() {
@Override
public void mouseReleased(MouseEvent e) {
if (e.getSource() == list) {
if (list.getModel().getSize() > 0) {
// JList mouse listener
if (comboBox.getSelectedIndex() == list.getSelectedIndex()) {
comboBox.getEditor().setItem(list.getSelectedValue());
}
comboBox.setSelectedIndex(list.getSelectedIndex());
}
// comboBox.setPopupVisible(false);
// workaround for cancelling an edited item (bug 4530953)
if (comboBox.isEditable() && comboBox.getEditor() != null) {
comboBox.configureEditor(comboBox.getEditor(),
comboBox.getSelectedItem());
}
return;
}
// JComboBox mouse listener
Component source = (Component)e.getSource();
Dimension size = source.getSize();
Rectangle bounds = new Rectangle( 0, 0, size.width - 1, size.height - 1 );
if ( !bounds.contains( e.getPoint() ) ) {
MouseEvent newEvent = convertMouseEvent( e );
Point location = newEvent.getPoint();
Rectangle r = new Rectangle();
list.computeVisibleRect( r );
if ( r.contains( location ) ) {
if (comboBox.getSelectedIndex() == list.getSelectedIndex()) {
comboBox.getEditor().setItem(list.getSelectedValue());
}
comboBox.setSelectedIndex(list.getSelectedIndex());
}
// comboBox.setPopupVisible(false);
}
comboBox.setPopupVisible(true);
hasEntered = false;
stopAutoScrolling();
}
@Override
public void mousePressed(MouseEvent e) {
if (e.getSource() == list) {
return;
}
if (!SwingUtilities.isLeftMouseButton(e) || !comboBox.isEnabled())
return;
if ( comboBox.isEditable() ) {
Component comp = comboBox.getEditor().getEditorComponent();
if ((!(comp instanceof JComponent)) || ((JComponent)comp).isRequestFocusEnabled()) {
comp.requestFocus();
}
}
else if (comboBox.isRequestFocusEnabled()) {
comboBox.requestFocus();
}
togglePopup();
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseClicked(MouseEvent e) {
}
};
}
};
}
}
/////
package combo;
public class MultiCheckComboModel {
private String id;
Boolean isSelected;
public MultiCheckComboModel(String id, Boolean isSelected) {
this.id = id;
this.isSelected = isSelected;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Boolean getIsSelected() {
return isSelected;
}
public void setIsSelected(Boolean isSelected) {
this.isSelected = isSelected;
}
@Override
public String toString() {
return id+(isSelected?" is selected":" is not selected");
}
}
///////
package combo;
import java.awt.Color;
import java.awt.Component;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.ListCellRenderer;
public class MultiCheckComboRenderer implements ListCellRenderer{
private JCheckBox checkBox;
public MultiCheckComboRenderer() {
checkBox = new JCheckBox();
}
@Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
if(value instanceof MultiCheckComboModel){
MultiCheckComboModel comboModel = (MultiCheckComboModel) value;
checkBox.setText(comboModel.getId());
checkBox.setSelected(((Boolean) comboModel.getIsSelected()).booleanValue());
checkBox.setBackground(isSelected ? Color.LIGHT_GRAY : Color.white);
checkBox.setForeground(isSelected ? Color.white : Color.black);
return checkBox;
}
return new JLabel(value.toString());
}
public JCheckBox getCheckBox() {
return checkBox;
}
}