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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 00:53:15  来源:igfitidea点击:

How to disable certain items in a JComboBox

javaswingnetbeansjcombobox

提问by Daksh Shah

I have a ComboBoxin 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 JComboBoxthat 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 JComboBoxActionPerformedand 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;
    }
}

enter image description here

在此处输入图片说明

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]);
}

enter image description here

在此处输入图片说明

Here's a complete running example, using EnabledComboBoxRendererfrom 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();
}
}