禁用 JList 中的项目

Posted

技术标签:

【中文标题】禁用 JList 中的项目【英文标题】:Disable items in JList 【发布时间】:2012-01-10 18:40:12 【问题描述】:

我使用 JList 作为向导的一部分来显示要执行的所有步骤(它还允许单击一个步骤转到它)。根据前面步骤中完成的内容,并不总是需要某些步骤。我想在列表中禁用这些不适用的步骤。

如何禁用(防止选择)列表中的某些项目?有没有比继承 JList 并覆盖所有与选择相关的方法更好的方法?

【问题讨论】:

【参考方案1】:

如果您从列表模型中删除不适用的项目,而不是禁用它们会更容易。用户真的希望看到禁用的项目吗?我不认为它增加了任何价值,而是增加了视觉上的混乱。

【讨论】:

这是一个很好的观点。经过一番思考,我决定将它们变灰,但允许它们被选中。使用下一个/上一个时会跳过它们,但如果它们故意进入灰显步骤,则会显示一条消息,说明“启用”该步骤所需的操作【参考方案2】:

你必须实现DefaultListSelectionModel,然后你可以设置标志是否启用

简单例子

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class JListDisabledItemDemo implements ItemListener, Runnable 

    private JFrame f = new JFrame("Colors");
    private static final String ITEMS[] = " black ", " blue ", " green ",
        " orange ", " purple ", " red ", " white ", " yellow ";
    private JList jList;
    private JCheckBox[] checkBoxes;
    private boolean[] enabledFlags;

    @Override
    public void run() 
        JPanel pnlEnablers = new JPanel(new GridLayout(0, 1));
        pnlEnablers.setBorder(BorderFactory.createTitledBorder("Enabled Items"));
        checkBoxes = new JCheckBox[ITEMS.length];
        enabledFlags = new boolean[ITEMS.length];
        for (int i = 0; i < ITEMS.length; i++) 
            checkBoxes[i] = new JCheckBox(ITEMS[i]);
            checkBoxes[i].setSelected(true);
            checkBoxes[i].addItemListener(this);
            enabledFlags[i] = true;
            pnlEnablers.add(checkBoxes[i]);
        
        jList = new JList(ITEMS);
        jList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        jList.setSelectionModel(new DisabledItemSelectionModel());
        jList.setCellRenderer(new DisabledItemListCellRenderer());
        jList.addListSelectionListener(new ListSelectionListener() 

            @Override
            public void valueChanged(ListSelectionEvent e) 
                if (!e.getValueIsAdjusting()) 
                    System.out.println("selection");
                
            
        );
        JScrollPane scroll = new JScrollPane(jList);
        scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);

        Container contentPane = f.getContentPane();
        contentPane.setLayout(new GridLayout(1, 2));
        contentPane.add(pnlEnablers);
        contentPane.add(scroll);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setLocation(240, 280);
        UIManager.put("List.background", Color.lightGray);
        UIManager.put("List.selectionBackground", Color.orange);
        UIManager.put("List.selectionForeground", Color.blue);
        UIManager.put("Label.disabledForeground", Color.magenta);
        SwingUtilities.updateComponentTreeUI(f);
        f.pack();
        javax.swing.SwingUtilities.invokeLater(new Runnable() 

            @Override
            public void run() 
                f.setVisible(true);
            
        );
    

    @Override
    public void itemStateChanged(ItemEvent event) 
        JCheckBox checkBox = (JCheckBox) event.getSource();
        int index = -1;
        for (int i = 0; i < ITEMS.length; i++) 
            if (ITEMS[i].equals(checkBox.getText())) 
                index = i;
                break;
            
        
        if (index != -1) 
            enabledFlags[index] = checkBox.isSelected();
            jList.repaint();
        
    

    public static void main(String args[]) 
        SwingUtilities.invokeLater(new JListDisabledItemDemo());
    

    private class DisabledItemListCellRenderer extends DefaultListCellRenderer 

        private static final long serialVersionUID = 1L;

        @Override
        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) 
            Component comp = super.getListCellRendererComponent(list, value, index, false, false);
            JComponent jc = (JComponent) comp;
            if (enabledFlags[index]) 
                if (isSelected & cellHasFocus) 
                    comp.setForeground(Color.black);
                    comp.setBackground(Color.red);
                 else 
                    comp.setForeground(Color.blue);
                
                if (!isSelected) 
                    if ((value.toString()).trim().equals("yellow")) 
                        comp.setForeground(Color.orange);
                        comp.setBackground(Color.magenta);
                    
                
                return comp;
            
            comp.setEnabled(false);
            return comp;
        
    

    private class DisabledItemSelectionModel extends DefaultListSelectionModel 

        private static final long serialVersionUID = 1L;

        @Override
        public void setSelectionInterval(int index0, int index1) 
            if (enabledFlags[index0]) 
                super.setSelectionInterval(index0, index0);
             else 
                /*
                 * The previously selected index is before this one,
                 * so walk forward to find the next selectable item.
                 */
                if (getAnchorSelectionIndex() < index0) 
                    for (int i = index0; i < enabledFlags.length; i++) 
                        if (enabledFlags[i]) 
                            super.setSelectionInterval(i, i);
                            return;
                        
                    
                 /*
                 * Otherwise, walk backward to find the next selectable item.
                 */ else 
                    for (int i = index0; i >= 0; i--) 
                        if (enabledFlags[i]) 
                            super.setSelectionInterval(i, i);
                            return;
                        
                    
                
            
        
    

【讨论】:

当您想显示禁用的项目时,这是一个很好的答案。在某些用例中,实际上这样做更好。我有这样一个用例,这就像一个魅力。【参考方案3】:

一种解决方案:您可能想在 Java API 中查找 AbstractAction。然后,实现 COMMAND 模式。

这个想法是通过将它们变成类(实现 AbstractAction)来赋予方法状态。然后,它们可以互相禁用。

http://en.wikipedia.org/wiki/Command_pattern

http://docs.oracle.com/javase/6/docs/api/

【讨论】:

【参考方案4】:

我想要一个包含无法选择且透明的单元格的 JList。所以这就是我所做的:

class DisabledItemListCellRenderer extends JLabel implements ListCellRenderer<Object> 

    private static final long serialVersionUID = 1L;

    public DisabledItemListCellRenderer() 
        setOpaque(false);
    

    @Override
    public Component getListCellRendererComponent(JList<?> list, Object value,
            int index, boolean isSelected, boolean cellHasFocus) 
        String txt = (String) value;
        setText(txt);

        return this;
           

【讨论】:

以上是关于禁用 JList 中的项目的主要内容,如果未能解决你的问题,请参考以下文章

JList 项中的自动换行

Java JList 滚动到所选项目

使用 DefaultListModel 将项目从 ArrayList 添加到 JList

是否可以更改 Java Swing jList 中项目的名称*显示*?

Java swing弹出菜单和jlist

检索 JList 项的数组数据