2

我正在使用 Swing 编写 GUI。我有一个JComboBox使用 aListCellRenderer和 a编写的自定义BasicComboBoxEditor

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

第一张图片显示了选择前界面的外观,第二张展示了选择后的外观。

在进行选择之前 选择完成后

问题

如何将“选择”的背景更改为“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 中移除焦点。

简单地做 asetFocusable(false)会修复它,但也会带走程序其余部分的一些功能,所以这是不希望的。

4

2 回答 2

4
  • 为了获得更好的帮助,请尽快在局部变量中发布一个SSCCE / MCVE简短的、可运行的、可编译的、带有硬编码值的JComboBox/XxxComboBoxModel
  • JList 在 API 中默认实现了布尔数组(不知道隐藏的内容 String trueFalseItem = Boolean.toString(tempValue);和存储的值JComboBox model
  • 这只是测试isSelected和更改JList.setSelectionXxx内部的最少代码DefaultListCellRenderer

例如(SSCCE / MCVE 形式的代码)

在此处输入图像描述

.

在此处输入图像描述

.

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();
            }
        });
    }
}
于 2016-07-05T10:38:29.430 回答
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);
}

(大部分功劳归功于这个答案

于 2016-07-06T13:23:56.743 回答