Java 如何禁用 JComboBox 中的某些项目
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23722706/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to disable certain items in a JComboBox
提问by Daksh Shah
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.
我有一个ComboBox
我有 8 个项目,除了在特定条件下,我想显示所有项目,用户应该只能选择其中的前两个,所以我已经编程,如果条件为真并且用户选择任何其他选项,然后它会显示一个消息框"You cannot choose this"
,然后自动选择默认值。到现在为止还挺好。
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.
但现在的问题是,用户无法通过查看JComboBox
他可以选择的选项来判断,所以我想要做的是,如果条件为真,那么除了前两个选项之外的所有选项都应该被禁用(或灰色或其他),以便用户可以确定您无法选择它,如果他们仍然选择它,那么我的消息框应该会出现。
What I tried: I tried looking up thisbut 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
注意:我正在使用 Netbeans GUI 来创建所有内容,并且我正在编写的代码正在编写中JComboBoxActionPerformed
,我是新手,所以我无法弄清楚自己,为此道歉
回答by Paul Samsotha
First of all...
首先...
This is going to require some hand coding. The GUI Builder is not going to help you out here.
这将需要一些手工编码。GUI Builder 不会在这里帮助您。
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 disablefashion, by change the foreground color and it's selection background.
你可以实现你自己的BasicComboBoxRenderer
,你传递给它一个ListSelectionModel
. 根据您传递给它的模型,只有选定的间隔将使用标准渲染器进行渲染。其余的索引将以禁用方式呈现,通过更改前景色和它的选择背景。
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
您可以使用两个单独的侦听器。一种用于启用项目时,另一种用于禁用项目时。启用项目后,您可以1.更改选择模型2.添加启用的侦听器3.移除禁用的侦听器
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
这是一个完整的运行示例,EnabledComboBoxRenderer
从上面使用
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();
}
});
}
}
回答by Paul Efford
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:
为了解决@Samsotha 的代码“问题”,其中禁用的项目仍然可以选择,我找到并修改了一个代码,该代码可以很好地用于此目的。这是一个关于如何调用它并以类似于 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();
}
}