问题
I have a ComboBox
in which I have 8 Items out of which I want to display all but on a certain condition, the user should only be able to select the first two of them, so I have programmed that if the condition is true and the user chooses any other option then it shows up a Message Box showing "You cannot choose this"
and then selecting the default automatically. So far so good.
But now the thing is that the user cannot make out by seeing the options of JComboBox
that which ones can he select, So what I want to do is that if the condition is true then all the options other than the first two should be disabled(or grey out or something) so that users can make out that you cannot select it, and if they still do then my Message Box should come up.
What I tried: I tried looking up this but I couldn't make out what was done in the question (it's answer is for no use for me) and I also tried other options but was unsuccessful.
Note: I am using Netbeans GUI to create everything, and the code I am writing is on JComboBoxActionPerformed
and I am a newbie so I couldn't figure out myself, apologies for that
回答1:
First of all...
This is going to require some hand coding. The GUI Builder is not going to help you out here.
As for the rendering...
You can implement your own BasicComboBoxRenderer
, where you pass to it a ListSelectionModel
. Based on the model you pass to it, only the selected interval will get rendered with the standard renderer. The remaining indices will get rendered in a disable fashion, by change the foreground color and it's selection background.
Note: this is only going to affect the rendering of the items, not the actual selection events
import java.awt.Color;
import java.awt.Component;
import javax.swing.JList;
import javax.swing.ListSelectionModel;
import javax.swing.UIManager;
import javax.swing.plaf.basic.BasicComboBoxRenderer;
public class EnabledComboBoxRenderer extends BasicComboBoxRenderer {
private ListSelectionModel enabledItems;
private Color disabledColor = Color.lightGray;
public EnabledComboBoxRenderer() {}
public EnabledComboBoxRenderer(ListSelectionModel enabled) {
super();
this.enabledItems = enabled;
}
public void setEnabledItems(ListSelectionModel enabled) {
this.enabledItems = enabled;
}
public void setDisabledColor(Color disabledColor) {
this.disabledColor = disabledColor;
}
@Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
Component c = super.getListCellRendererComponent(list, value, index,
isSelected, cellHasFocus);
if (!enabledItems.isSelectedIndex(index)) {// not enabled
if (isSelected) {
c.setBackground(UIManager.getColor("ComboBox.background"));
} else {
c.setBackground(super.getBackground());
}
c.setForeground(disabledColor);
} else {
c.setBackground(super.getBackground());
c.setForeground(super.getForeground());
}
return c;
}
}
As for selecting items...
You can use two separate listeners. One for when the items are enabled and one for when the items are disabled. When the items are enabled, you can 1. Change the selection model 2. Add the enabled listener 3. Remove the disabled listener
private class EnabledListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println(((JComboBox) e.getSource()).getSelectedItem());
}
}
private class DisabledListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
if (((JComboBox) e.getSource()).getSelectedIndex() != SELECTION_INTERVAL[0]
&& ((JComboBox) e.getSource()).getSelectedIndex() != SELECTION_INTERVAL[1]) {
JOptionPane.showMessageDialog(null,
"You can't Select that Item", "ERROR",
JOptionPane.ERROR_MESSAGE);
} else {
System.out.println(((JComboBox) e.getSource())
.getSelectedItem());
}
}
}
protected void enableItemsInComboBox() {
comboBox.removeActionListener(disabledListener);
comboBox.addActionListener(enabledListener);
model.setSelectionInterval(SELECTION_INTERVAL[0], comboBox.getModel()
.getSize() - 1);
}
And vice versa
protected void disableItemsInComboBox() {
comboBox.removeActionListener(enabledListener);
comboBox.addActionListener(disabledListener);
model.setSelectionInterval(SELECTION_INTERVAL[0], SELECTION_INTERVAL[1]);
}
Here's a complete running example, using EnabledComboBoxRenderer
from above
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.DefaultListSelectionModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
public class ComboBoxDisabledItemsDemo {
private static final int[] SELECTION_INTERVAL = { 0, 1 };
private JComboBox comboBox;
private JCheckBox disableCheckBox;
private DefaultListSelectionModel model = new DefaultListSelectionModel();
private EnabledComboBoxRenderer enableRenderer = new EnabledComboBoxRenderer();
private EnabledListener enabledListener = new EnabledListener();
private DisabledListener disabledListener = new DisabledListener();
public ComboBoxDisabledItemsDemo() {
comboBox = createComboBox();
disableCheckBox = createCheckBox();
disableCheckBox.setSelected(true); // this adds the action listener to
// the
// to the combo box
JFrame frame = new JFrame("Disabled Combo Box Items");
frame.setLayout(new GridBagLayout());
frame.add(comboBox);
frame.add(disableCheckBox);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private JComboBox createComboBox() {
String[] list = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5",
"Item 6", "Item 7" };
JComboBox cbox = new JComboBox(list);
model.addSelectionInterval(SELECTION_INTERVAL[0], SELECTION_INTERVAL[1]);
enableRenderer.setEnabledItems(model);
cbox.setRenderer(enableRenderer);
return cbox;
}
private class EnabledListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println(((JComboBox) e.getSource()).getSelectedItem());
}
}
private class DisabledListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
if (((JComboBox) e.getSource()).getSelectedIndex() != SELECTION_INTERVAL[0]
&& ((JComboBox) e.getSource()).getSelectedIndex() != SELECTION_INTERVAL[1]) {
JOptionPane.showMessageDialog(null,
"You can't Select that Item", "ERROR",
JOptionPane.ERROR_MESSAGE);
} else {
System.out.println(((JComboBox) e.getSource())
.getSelectedItem());
}
}
}
protected void disableItemsInComboBox() {
comboBox.removeActionListener(enabledListener);
comboBox.addActionListener(disabledListener);
model.setSelectionInterval(SELECTION_INTERVAL[0], SELECTION_INTERVAL[1]);
}
protected void enableItemsInComboBox() {
comboBox.removeActionListener(disabledListener);
comboBox.addActionListener(enabledListener);
model.setSelectionInterval(SELECTION_INTERVAL[0], comboBox.getModel()
.getSize() - 1);
}
private JCheckBox createCheckBox() {
JCheckBox checkBox = new JCheckBox("diabled");
checkBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
disableItemsInComboBox();
} else if (e.getStateChange() == ItemEvent.DESELECTED) {
enableItemsInComboBox();
}
}
});
return checkBox;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ComboBoxDisabledItemsDemo();
}
});
}
}
回答2:
To solve @Samsotha 's code "problem" where disabled items are still selectable, I found and adapted a code which works fine for this purpose. Here is a working example on how you can call it and use it in similar way to a JComboBox:
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.ListCellRenderer;
import javax.swing.UIManager;
import javax.swing.plaf.basic.BasicComboBoxRenderer;
/**
* Creates a util class to generate a JComboBox with enabled/disabled items.
* Strongly adapted from original post of Joris Van den Bogaert at http://esus.com/disabling-some-of-the-elements-in-a-jcombobox/
*/
@SuppressWarnings({ "unchecked" })
public class MyComboBox extends JComboBox<Object> {
private static final long serialVersionUID = 6975854742812751380L;
/**************************************************
* FOR TESTING:
*/
public static void main(String[] args) throws Exception {
// Way 1: load an array
ConditionalItem[] arr = new ConditionalItem[] {
new ConditionalItem("Item 0", false),
new ConditionalItem("Item 1", false),
new ConditionalItem("Item 2"),
new ConditionalItem("Item 3", false),
new ConditionalItem("Item 4", true)
};
MyComboBox combo = new MyComboBox(arr);
// // Way 2: load oned by one (allows run-time modification)
// MyComboBox combo = new MyComboBox();
// combo.addItem("sss", false);
// combo.addItem("ddd", true);
// combo.addItem("eeee");
// Way 3: initial load and oned by one on run-time
combo.addItem("Item 5");
combo.addItem("Item 6", false);
combo.addItem("Item 7", true);
JPanel panel = new JPanel(new FlowLayout());
panel.add(new JLabel("Test:"));
panel.add(combo);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(panel);
frame.pack();
frame.setVisible(true);
Thread.sleep(2*1000);
combo.setItem("Item 2", false);
Thread.sleep(2*1000);
combo.setItem("Item 8", false);
}
/**************************************************
* CONSTRUCTORS:
*/
ActionListener listener;
public MyComboBox() {
this.setRenderer(new ConditionalComboBoxRenderer());
}
public MyComboBox(ConditionalItem[] arr) {
for(ConditionalItem ci : arr) {
this.addItem(ci);
}
this.setRenderer(new ConditionalComboBoxRenderer());
listener = new ConditionalComboBoxListener(this);
this.addActionListener(listener);
}
public void addItem(String str) {
addItem(new ConditionalItem(str, true));
}
public void addItem(String str, boolean bool) {
addItem(new ConditionalItem(str, bool));
}
public void addItem(Component ci) {
this.add(ci);
this.setRenderer(new ConditionalComboBoxRenderer());
this.addActionListener(new ConditionalComboBoxListener(this));
}
/** if combobox contains "str", sets its state to "bool";
* if it's not yet an item, ignores it;
* the method also re-sets the selected item to the first one
* shown in the list as "true", and disables the listeners in this
* process to avoid firing an action when reorganizing the list.
*/
public void setItem(String str, boolean bool) {
int n = this.getItemCount();
for (int i=0; i<n; i++) {
if(this.getItemAt(i).toString().equals(str)) {
this.removeActionListener(listener);
this.removeItemAt(i);
this.insertItemAt(new ConditionalItem(str, bool), i);
int k = this.firstTrueItem();
if(k<0) k=0; // default index 0 if no true item is shown as true
this.setSelectedIndex(k);
this.addActionListener(listener);
return;
}
}
System.err.println("Warning: item "+ str +" is not a member of this combobox: ignoring it...");
}
public Object[] getItems() {
int n = this.getItemCount();
Object[] obj = new Object[n];
for (int i=0; i<n; i++) {
obj[i] = this.getItemAt(i);
}
return obj;
}
/** @return -1 if no item is true */
int firstTrueItem() {
int i = 0;
for(Object obj : this.getItems()) {
if(((ConditionalItem) obj).isEnabled()) return i;
i++;
}
return -1;
}
}
@SuppressWarnings("rawtypes")
class ConditionalComboBoxRenderer extends BasicComboBoxRenderer implements ListCellRenderer {
private static final long serialVersionUID = 8538079002036282063L;
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
boolean cellHasFocus) {
if (isSelected) {
setBackground(list.getSelectionBackground());
setForeground(list.getSelectionForeground());
} else {
setBackground(list.getBackground());
setForeground(list.getForeground());
}
try {
if (value != null && !((ConditionalItem) value).isEnabled()) {
setBackground(list.getBackground());
setForeground(UIManager.getColor("Label.disabledForeground"));
}
} catch(Exception e) {
e.printStackTrace();
} finally {
setFont(list.getFont());
setText((value == null) ? "" : value.toString());
}
return this;
}
}
class ConditionalComboBoxListener implements ActionListener {
MyComboBox combobox;
Object oldItem;
ConditionalComboBoxListener(MyComboBox combobox) {
this.combobox = combobox;
combobox.setSelectedIndex(combobox.firstTrueItem());
oldItem = combobox.getSelectedItem();
}
public void actionPerformed(ActionEvent e) {
Object selectedItem = combobox.getSelectedItem();
if (!((ConditionalItem) selectedItem).isEnabled()) {
combobox.setSelectedItem(oldItem);
System.err.println(selectedItem.toString());
} else {
oldItem = selectedItem;
System.out.println(oldItem.toString());
}
}
}
class ConditionalItem {
Object object;
boolean isEnabled;
ConditionalItem(Object object, boolean isEnabled) {
this.object = object;
this.isEnabled = isEnabled;
}
ConditionalItem(Object object) {
this(object, true);
}
public boolean isEnabled() {
return isEnabled;
}
public void setEnabled(boolean isEnabled) {
this.isEnabled = isEnabled;
}
@Override
public String toString() {
return object.toString();
}
}
来源:https://stackoverflow.com/questions/23722706/how-to-disable-certain-items-in-a-jcombobox