Recently, I was working on a project in Java and needed to have a combo box, but with certain items in the list disabled (e.g. gray and non-selectable). At first, I simply set a custom renderer for the combo box which checked if the item was disabled. That, however, did not prevent the items from being selected. Thus, I set about to find a viable solution. There are plenty of solutions out there, but none seemed to work exactly the way I wanted. In the end, I ended up subclassing JComboBox to provide the functionality of disabling individual items. Here is my result, in under 100 lines:
As you can see, most of the code is pretty straightforward, adding and removing elements from the JComboBox and the list of item states. The custom renderer is still used to provide the L&F for the disabled items, but the key to having the disabled items non-selectable is the setSelectedIndex(int) method. There are also plenty of index range checks thrown in there, especially in the custom renderer, as the combo box calls that method with index = -1 when rendering the combo box in its "closed" state (without the dropdown).
Of course, I want give credit to some other blogs that helped lay the groundwork and point me in the right direction, but unfortunately I don't remember their names. If I find them again, I'll be sure to include them in this post.
As always, please let me know if you find this useful, or if you find any bugs or possible improvements.
import java.awt.Component; import java.util.ArrayList; import javax.swing.JComboBox; import javax.swing.JList; import javax.swing.plaf.basic.BasicComboBoxRenderer; public class PartialDisableComboBox extends JComboBox { private static final long serialVersionUID = -1690671707274328126L; private ArrayList<boolean> itemsState = new ArrayList<boolean>(); public PartialDisableComboBox() { super(); this.setRenderer(new BasicComboBoxRenderer() { private static final long serialVersionUID = -2774241371293899669L; @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); boolean disabled = index >= 0 && index < itemsState.size() && !itemsState.get(index); c.setEnabled(!disabled); c.setFocusable(!disabled); return c; } }); } @Override public void addItem(Object item) { this.addItem(item, true); } public void addItem(Object item, boolean enabled) { super.addItem(item); itemsState.add(enabled); } @Override public void insertItemAt(Object item, int index) { this.insertItemAt(item, index, true); } public void insertItemAt(Object item, int index, boolean enabled) { super.insertItemAt(item, index); itemsState.add(index, enabled); } @Override public void removeAllItems() { super.removeAllItems(); itemsState.clear(); } @Override public void removeItemAt(int index) { if (index < 0 || index >= itemsState.size()) throw new IllegalArgumentException("Item Index out of Bounds!"); super.removeItemAt(index); itemsState.remove(index); } @Override public void removeItem(Object item) { for (int q = 0; q < this.getItemCount(); q++) { if (this.getItemAt(q) == item) itemsState.remove(q); } super.removeItem(item); } @Override public void setSelectedIndex(int index) { if (index < 0 || index >= itemsState.size()) throw new IllegalArgumentException("Item Index out of Bounds!"); if (itemsState.get(index)) super.setSelectedIndex(index); } public void setItemEnabled(int index, boolean enabled) { if (index < 0 || index >= itemsState.size()) throw new IllegalArgumentException("Item Index out of Bounds!"); itemsState.set(index, enabled); } public boolean isItemEnabled(int index) { if (index < 0 || index >= itemsState.size()) throw new IllegalArgumentException("Item Index out of Bounds!"); return itemsState.get(index); } }
As you can see, most of the code is pretty straightforward, adding and removing elements from the JComboBox and the list of item states. The custom renderer is still used to provide the L&F for the disabled items, but the key to having the disabled items non-selectable is the setSelectedIndex(int) method. There are also plenty of index range checks thrown in there, especially in the custom renderer, as the combo box calls that method with index = -1 when rendering the combo box in its "closed" state (without the dropdown).
Of course, I want give credit to some other blogs that helped lay the groundwork and point me in the right direction, but unfortunately I don't remember their names. If I find them again, I'll be sure to include them in this post.
As always, please let me know if you find this useful, or if you find any bugs or possible improvements.
This comment has been removed by the author.
ReplyDeleteThis is working great (just had to make a quick change from boolean to Boolean for private ArrayList (maybe a Java7 thing?). Just what I needed. Thanks.
ReplyDeleteThe player wins the prize if the symbols line up with the profitable payline. Machines are also identified to intentionally put aside money, which is later awarded in a sequence of wins, {known as|generally identified as|often identified as} a "streak". The minimum payout percentage is 70%, with pubs typically setting the payout at round 78%. A slot machine's standard layout contains a display displaying SM카지노 three or extra reels that "spin" when the game is activated. Some fashionable slot machines still embrace a lever as a skeuomorphic design trait to trigger play.
ReplyDelete