仅更改可编辑JComboBox的文本字段背景颜色

时间:2014-06-13 11:45:23

标签: java swing optimization jcombobox

经过一番研究后,我想出了一条出路,只改变了可编辑JComboBox文本区域的背景颜色,但还有更好的方法吗?

我想要的是什么:

我的结果应如下所示:

enter image description here

我现在在做什么:

为了澄清,我已经得到了上面的结果,但我认为实现它的代码实在太过分了,因为在第一步中我用所需颜色绘制所有内容(文本字段,按钮和列表)。然后我从按钮中删除颜色,然后通过BasicComboBoxRenderer从列表中删除颜色。

我的代码:

public static void changeOnlyEditorBackgroundColorOfEditableJComboBox(final JComboBox cb, final Color color) {
    //paint the whole ComboBox
    cb.getEditor().getEditorComponent().setBackground(color);
    //remove the color from the button
    final Component[] comps = cb.getComponents();
    for (int i = 0; i < comps.length; i++) { // hack valid only for Metal L&F
        if (comps[i] instanceof MetalComboBoxButton) {
            final MetalComboBoxButton coloredArrowsButton = (MetalComboBoxButton)comps[i];
            coloredArrowsButton.setBackground(null);
            break;
        }
    }
    //remove the color from the list
    cb.setRenderer(new RemoveColorFromComboBoxListRenderer());
}

private static class RemoveColorFromComboBoxListRenderer extends BasicComboBoxRenderer {

    // only slightly changed from the original implementation.
    @Override
    public Component getListCellRendererComponent(final JList list,
            final Object value,
            final int index,
            final boolean isSelected,
            final boolean cellHasFocus) {
        if (isSelected) {
            setBackground(list.getSelectionBackground());
            setForeground(list.getSelectionForeground());
        } else {
            // these lines were changed to always set the background white and the forground black
            setBackground(Color.white);
            setForeground(Color.black);
        }

        setFont(list.getFont());

        if (value instanceof Icon) {
            setIcon((Icon)value);
        } else {
            setText((value == null) ? "" : value.toString());
        }
        return this;
    }
}

所以我希望我能够监督一些事情并且有更好的方法来做到这一点。

最后,这是指向SSCCE的链接。

3 个答案:

答案 0 :(得分:1)

  • 我认为应该使用XxxRanderer

  • 使用JComboBox.getEditor()。getEditorComponent()。setBackground(Color.YELLOW);

  • 成功

enter image description here

e.g。 (UIManager的键只适用于不可编辑的JComboBox,奇怪但是......)

import java.awt.*;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.util.Vector;
import javax.swing.*;
import javax.swing.UIManager;
import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.metal.MetalComboBoxButton;

public class MyComboBox {

    private Vector<String> listSomeString = new Vector<String>();
    private JComboBox someComboBox = new JComboBox(listSomeString);
    private JComboBox editableComboBox = new JComboBox(listSomeString);
    private JComboBox non_EditableComboBox = new JComboBox(listSomeString);
    private JFrame frame;

    public MyComboBox() {
        listSomeString.add("-");
        listSomeString.add("Snowboarding");
        listSomeString.add("Rowing");
        listSomeString.add("Knitting");
        listSomeString.add("Speed reading");
//
        someComboBox.setPrototypeDisplayValue("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
        someComboBox.setFont(new Font("Serif", Font.BOLD, 16));
        someComboBox.setEditable(true);
        someComboBox.getEditor().getEditorComponent().setBackground(Color.YELLOW);
        ((JTextField) someComboBox.getEditor().getEditorComponent()).setBackground(Color.YELLOW);
        someComboBox.getEditor().getEditorComponent().addFocusListener(fcsListener);
//
        editableComboBox.setPrototypeDisplayValue("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
        editableComboBox.setFont(new Font("Serif", Font.BOLD, 16));
        editableComboBox.setEditable(true);
        JTextField text = ((JTextField) editableComboBox.getEditor().getEditorComponent());
        text.setBackground(Color.YELLOW);
        JComboBox coloredArrowsCombo = editableComboBox;
        Component[] comp = coloredArrowsCombo.getComponents();
        for (int i = 0; i < comp.length; i++) {
            if (comp[i] instanceof MetalComboBoxButton) {
                MetalComboBoxButton coloredArrowsButton = (MetalComboBoxButton) comp[i];
                coloredArrowsButton.setBackground(null);
                break;
            }
        }
        editableComboBox.getEditor().getEditorComponent().addFocusListener(fcsListener);
//
        non_EditableComboBox.setPrototypeDisplayValue("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
        non_EditableComboBox.setFont(new Font("Serif", Font.BOLD, 16));
        non_EditableComboBox.addFocusListener(fcsListener);
//
        frame = new JFrame();
        frame.setLayout(new GridLayout(0, 1, 10, 10));
        frame.add(someComboBox);
        frame.add(editableComboBox);
        frame.add(non_EditableComboBox);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocation(100, 100);
        frame.pack();
        frame.setVisible(true);
    }

    //
    private FocusListener fcsListener = new FocusListener() {

        @Override
        public void focusGained(FocusEvent e) {
            dumpInfo(e);
        }

        @Override
        public void focusLost(FocusEvent e) {
            dumpInfo(e);
        }

        private void dumpInfo(FocusEvent e) {
            final Component c = e.getComponent();
            System.out.println("Source  : " + name(e.getComponent()));
            System.out.println("Opposite : " + name(e.getOppositeComponent()));
            System.out.println("Temporary: " + e.isTemporary());
            if (c instanceof JFormattedTextField) {//works for editable JComboBox too
                SwingUtilities.invokeLater(new Runnable() {

                    @Override
                    public void run() {
                        ((JFormattedTextField) c).selectAll();
                    }
                });
            } else if (c instanceof JTextField) {
                SwingUtilities.invokeLater(new Runnable() {

                    @Override
                    public void run() {
                        ((JTextField) c).selectAll();
                    }
                });
            } else if (c instanceof JTextField) {
                SwingUtilities.invokeLater(new Runnable() {

                    @Override
                    public void run() {
                        ((JComboBox) c).getEditor().selectAll();
                    }
                });
            }
        }

        private String name(Component c) {
            return (c == null) ? null : c.getName();
        }
    };

    public static void main(String[] args) {
        UIManager.put("ComboBox.background", new ColorUIResource(Color.yellow));
        UIManager.put("JTextField.background", new ColorUIResource(Color.yellow));
        UIManager.put("ComboBox.selectionBackground", new ColorUIResource(Color.magenta));
        UIManager.put("ComboBox.selectionForeground", new ColorUIResource(Color.blue));
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                MyComboBox aCTF = new MyComboBox();
            }
        });
    }
}

答案 1 :(得分:0)

我发现了这种奇怪的行为。 myComboBox位于JBAlet中的JPanel中:

private javax.swing.JComboBox myComboBox = new javax.swing.JComboBox();

// This works:
myComboBox.setBackground(Color.yellow);
// This works too:
myComboBox.setBackground(new Color(255, 255, 0));

// This works NOT! Background is now white (= default color of JComboBox)
// but should be light yellow.
myComboBox.setBackground(new Color(255, 255, 150));

答案 2 :(得分:0)

我对前景色有同样的问题,但问题似乎只发生在默认的L&amp; F,当使用例如系统L&amp; F组件的行为与预期一致。 我曾经按照以下解决方案更改列表项的颜色。

combobox.setRenderer(new DefaultListCellRenderer() {
  @Override
  public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
    Component comp = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
    if (index != -1) comp.setForeground(UIManager.getColor("List.foreground"));
    return comp;
  }
});

combobox.getEditor().getEditorComponent().setForeground(Color.RED);