在JComboBox中更改选择的颜色(选择后)

时间:2016-07-05 09:58:50

标签: java swing jcombobox listcellrenderer

我正在使用Swing编写GUI。我使用JComboBoxListCellRenderer自定义了BasicComboBoxEditor

在我的getListCellRendererComponent()方法中,我根据项目是否“选中”(鼠标悬停在上面)更改列表的颜色,这很好,但是我不希望选择一旦做出选择就改变背景颜色,它目前正在做。

第一张图片展示了界面在进行选择之前的外观,第二张图片展示了它如何照顾。

Before selection is made After selection is made

问题

如何将“选择”的背景更改为“stockColor”?

MCVE

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.util.Vector;

import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
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.plaf.basic.BasicComboBoxEditor;

public class TFComboBox extends JComboBox{

    public static void main(String[] args){     
        createAndShowGUI();
    }

    public static void createAndShowGUI(){
        JFrame frame = new JFrame("MCVE");

        JPanel pane = new JPanel(new BorderLayout());
        TFComboBox cb = new TFComboBox();
        boolean[] tf = {true, false};
        cb.addItems(tf);

        JButton b = new JButton("Click me!");

        pane.add(cb, BorderLayout.CENTER);
        pane.add(b, BorderLayout.LINE_END);

        frame.add(pane);

        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    private DefaultComboBoxModel model;
    private Vector<Boolean> comboBoxItems;
    private JComboBox comboBox;

    public TFComboBox(){
        comboBoxItems = new Vector<Boolean>();
        comboBoxItems.add(Boolean.TRUE);
        comboBoxItems.add(Boolean.FALSE);

        comboBox = new JComboBox(comboBoxItems);

        model = new DefaultComboBoxModel();
        setModel(model);
        setRenderer(new TrueFalseComboRenderer());
        setEditor(new TrueFalseComboEditor());
    }

    public void addItems(boolean[] items){
        for(boolean anItem : items){
            model.addElement(anItem);
        }
    }
}

class TrueFalseComboRenderer extends JPanel implements ListCellRenderer {

    private JLabel labelItem = new JLabel();
    private Color stockColor = labelItem.getBackground();

    public TrueFalseComboRenderer(){
        setLayout(new BorderLayout());
        labelItem.setOpaque(true);
        labelItem.setHorizontalAlignment(JLabel.CENTER);

        add(labelItem);

        setBackground(Color.LIGHT_GRAY);
    }

    @Override
    public Component getListCellRendererComponent(JList list, Object value, 
            int index, boolean isSelected, boolean cellHasFocus) {

        boolean tempValue = (boolean) value;    
        labelItem.setText(Boolean.toString(tempValue));

        if(isSelected){
            labelItem.setBackground(stockColor.darker());
            labelItem.setForeground(Color.WHITE);
        } else {
            labelItem.setBackground(stockColor);
            labelItem.setForeground(Color.BLACK);
        }

        return this;
    }   
}

class TrueFalseComboEditor extends BasicComboBoxEditor {

    private JLabel labelItem = new JLabel();
    private JPanel panel = new JPanel();
    private Object selectedItem;

    public TrueFalseComboEditor() {
        labelItem.setOpaque(false);
        labelItem.setHorizontalAlignment(JLabel.CENTER);
        labelItem.setForeground(Color.WHITE);

        panel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 2));
        panel.setBackground(Color.BLUE);
        panel.add(labelItem);
    }

    public Component getEditorComponent(){
        return this.panel;
    }

    public Object getItem(){
        return this.selectedItem;
    }

    public void setItem(Object item){
        if(item == null){
            return;
        }

        this.selectedItem = item;
        labelItem.setText(item.toString());
    }
}

修改

我添加了一个MCVE,你可以看到JComboBox关注的问题与我的问题有关。我在ComboBox旁边放了一个按钮,以帮助从ComboBox中删除焦点。

简单地执行setFocusable(false)会修复它,但也会删除程序其余部分的一些功能,所以这不是必需的。

2 个答案:

答案 0 :(得分:3)

  • 更快地发布SSCCE / MCVE,简短,可运行,可编辑,并在本地变量中使用JComboBox / XxxComboBoxModel的硬编码值
  • JList在API中默认实现了布尔数组(不知道隐藏在哪个中) String trueFalseItem = Boolean.toString(tempValue);并且值已存储JComboBox model
  • 这只是测试isSelected和更改JList.setSelectionXxxDefaultListCellRenderer的最低代码
例如

(SSCCE / MCVE形式的代码)

enter image description here

enter image description here

import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.util.Vector;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.SwingUtilities;

public class ComboBoxBooleanModel {

    private javax.swing.Timer timer = null;
    private Vector<Boolean> comboBoxItems;
    private JComboBox box;

    public ComboBoxBooleanModel() {
        comboBoxItems = new Vector<Boolean>();
        comboBoxItems.add(Boolean.TRUE);
        comboBoxItems.add(Boolean.FALSE);
        box = new JComboBox(comboBoxItems);
        box.setRenderer(new DefaultListCellRenderer() {
            @Override
            public Component getListCellRendererComponent(JList list, Object value,
                    int index, boolean isSelected, boolean cellHasFocus) {
                Component c = super.getListCellRendererComponent(
                        list, value, index, isSelected, cellHasFocus);
                if (c instanceof JLabel) {
                    JLabel l = (JLabel) c;
                    if (Boolean.TRUE.equals(value)) {
                        l.setBackground(Color.RED);
                        if (isSelected) {
                            list.setSelectionForeground(Color.RED);
                            list.setSelectionBackground(Color.BLUE);
                        }
                    } else if (Boolean.FALSE.equals(value)) {
                        l.setBackground(Color.BLUE);
                        if (isSelected) {
                            list.setSelectionForeground(Color.BLUE);
                            list.setSelectionBackground(Color.RED);
                        }
                    }
                    return l;
                }
                return c;
            }
        });
        JFrame frame = new JFrame("");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(box);
        frame.setLocationRelativeTo(null);
        frame.pack();
        frame.setVisible(true);
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                box.setSelectedIndex(1);
            }
        });
        start();
    }

    private void start() {
        timer = new javax.swing.Timer(2250, updateCol());
        timer.start();
    }

    public Action updateCol() {
        return new AbstractAction("text load action") {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                if (box.getSelectedItem() == (Boolean) false) {
                    box.setSelectedItem((Boolean) true);
                } else {
                    box.setSelectedItem((Boolean) false);
                }
            }
        };
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                ComboBoxBooleanModel comboBoxModel = new ComboBoxBooleanModel();
            }
        });
    }
}

答案 1 :(得分:0)

以下是2个JCombos的简短演示,其中一个在选择时不会改变其背景颜色:

public static void main(String[] args){

    JFrame frame = new JFrame("Combos BG Color test");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLocationRelativeTo(null);
    frame.getContentPane().setPreferredSize(new Dimension(400, 40));

    JPanel mainPanel = new JPanel();
    mainPanel.setLayout(new GridLayout(1,2));
    frame.add(mainPanel);

    JComboBox<String> aCombo = new JComboBox<>(new String[]{"A","B","C"});
    mainPanel.add(aCombo);

    JComboBox<String> bCombo = new JComboBox<>(new String[]{"1","2","3"});
    Color bgColor = bCombo.getBackground();
    bCombo.setRenderer(new DefaultListCellRenderer() {
        @Override
        public void paint(Graphics g) {
            setBackground(bgColor);
            super.paint(g);
        }
    });

    mainPanel.add(bCombo);
    frame.pack();
    frame.setVisible(true);
}

(大部分功劳归于此answer