Colored jcombobox with colored elements and focus

I am trying to make a color dropdown with colored elements (see code below). Color is applied after the drop-down field loses focus.

Is this the right behavior?

How can I change the color of the foreground and / or background when the selected area has focus?

thank

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;
public class DropDown {
    enum Colors {
        red(Color.red), orange(Color.orange), green(Color.green), yellow(Color.yellow), blue(Color.blue);
        Colors(Color color) {
            this.color = color;
        }
        static String[] listModel() {
            java.util.List<Colors> values = Arrays.asList(values());
            String s = values.toString().replaceAll(" ", "");
            return s.substring(1, s.length() - 1).split(",");
        }
        final Color color;
    }
    static class ColoredCellRenderer implements ListCellRenderer {
        protected DefaultListCellRenderer defaultRenderer = new DefaultListCellRenderer();
        private final static Dimension preferredSize = new Dimension(0, 20);
        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
                boolean cellHasFocus) {
            JLabel renderer = (JLabel) defaultRenderer.getListCellRendererComponent(list, value, index, isSelected,
                    cellHasFocus);
            if (index != -1) if (value instanceof String) renderer.setForeground(Colors.valueOf((String) value).color);
            else
                System.out.println("not a string");
            else
                System.out.println("in getListCellRendererComponent, index=-1");
            renderer.setPreferredSize(preferredSize);
            return renderer;
        }
    }
    private static JComboBox addLabeledComboBox(Container c, String label, String[] model) {
        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
        Border border = BorderFactory.createLineBorder(Color.green, 1);
        panel.setBorder(border);
        JLabel l = new JLabel(label);
        panel.add(l);
        final JComboBox comboBox = new JComboBox(model);
        comboBox.setName(label);
        l.setLabelFor(comboBox);
        comboBox.setRenderer(new ColoredCellRenderer());
        panel.add(comboBox);
        c.add(panel);
        return comboBox;
    }
    private static void addContent(Container c) {
        c.setLayout(new BoxLayout(c, BoxLayout.Y_AXIS));
        ActionListener actionListener = new ActionListener() {
            @Override public void actionPerformed(ActionEvent e) {
                if (e.getSource() instanceof JComboBox) {
                    final JComboBox comboBox = (JComboBox) e.getSource();
                    Object selected = comboBox.getSelectedItem();
                    String string = (String) selected;
                    Color color = Colors.valueOf(string).color;
                    int i = comboBox.getSelectedIndex();
                    if (i != -1) {
                        System.out.println("comboBox " + comboBox.getName() + " " + color);
                        comboBox.setForeground(color);
                        System.out.println(comboBox.hasFocus());
                        // comboBox.repaint();
                    } else
                        System.out.println("in actionListener selected=" + selected);
                } else
                    System.out.println("in actionListener selected is not a comboBox");
            }
        };
        c.add(new JButton("button"));
        for (int i = 0; i < 2; i++) {
            JPanel panel = new JPanel();
            Border border = BorderFactory.createLineBorder(Color.red, 1);
            panel.setBorder(border);
            panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
            panel.add(new JLabel("label " +(i+1)));
            JComboBox comboBox = addLabeledComboBox(panel, "" + (i + 1), Colors.listModel());
            comboBox.addActionListener(actionListener);
            comboBox.setSelectedIndex(0); // select something
            c.add(panel);
        }
    }
    private static void createAndShowGUI() {
        JFrame frame = new JFrame("Colored JComboBox");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        addContent(frame.getContentPane());
        frame.pack();
        frame.setVisible(true);
    }
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            @SuppressWarnings("synthetic-access") public void run() {
                createAndShowGUI();
            }
        });
    }
}
+3
source share
3 answers

Here is another approach:

//JList#setSelectionForeground(...) version
static class ColoredCellRenderer implements ListCellRenderer {
  protected DefaultListCellRenderer defaultRenderer = new DefaultListCellRenderer();
  private final Color selectionBackground = new Color(240,200,200);
  public Component getListCellRendererComponent(
      JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
    Color fgc = Colors.valueOf((String)value).color;
    if(index<0) {
      //comboBox.setForeground(fgc); //Windows, CDE/Motif Look & Feel
      list.setSelectionForeground(fgc);
      list.setSelectionBackground(selectionBackground);
    }
    JLabel renderer = (JLabel) defaultRenderer.getListCellRendererComponent(
        list, value, index, isSelected, cellHasFocus);
    if (index != -1) {
      renderer.setForeground(fgc);
    }
    return renderer;
  }
}

//html version
static class ComboHtmlRenderer extends DefaultListCellRenderer {
  private final Color selectionBackground = new Color(240,200,200);
  @Override public Component getListCellRendererComponent(
      JList list, Object value, int index, boolean isSelected, boolean hasFocus) {
    Color fgc = Colors.valueOf((String)value).color;
    if(index<0) {
      list.setSelectionBackground(selectionBackground);
    }
    JLabel l = (JLabel)super.getListCellRendererComponent(
                 list, value, index, isSelected, hasFocus);
    l.setText("<html><font color="+hex(fgc)+">"+value);
    l.setBackground(isSelected?selectionBackground:list.getBackground());
    return l;
  }
  private static String hex(Color c) {
    return String.format("#%06x", c.getRGB()&0xffffff);
  }
}
+4
source

separate Editor and Renderer and add these two methods to DefaultListCellRenderer

  • cellHasFocus

  • Isselected

Example

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.LineBorder;
import javax.swing.event.EventListenerList;

class ColorComboBoxEditor1 implements ComboBoxEditor {

    final protected JLabel editor;
    //final protected JButton editor;
    private EventListenerList listenerList = new EventListenerList();

    ColorComboBoxEditor1(Color initialColor) {
        editor = new JLabel("");
        /*editor = new JButton("");
        editor.setBackground(initialColor);
        ActionListener actionListener = new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                Color currentBackground = editor.getBackground();
                Color color = JColorChooser.showDialog(editor, "Color Chooser", currentBackground);
                if ((color != null) && (currentBackground != color)) {
                    //editor.setBackground(color);
                    editor.setForeground(color);
                    fireActionEvent(color);
                }
            }
        };
        editor.addActionListener(actionListener);*/
    }

    @Override
    public void addActionListener(ActionListener l) {
        listenerList.add(ActionListener.class, l);
    }

    @Override
    public Component getEditorComponent() {
        return editor;
    }

    @Override
    public Object getItem() {
        return editor.getBackground();
    }

    @Override
    public void removeActionListener(ActionListener l) {
        listenerList.remove(ActionListener.class, l);
    }

    @Override
    public void selectAll() {
    }

    @Override
    public void setItem(Object newValue) {
        if (newValue instanceof Color) {
            Color color = (Color) newValue;
            //editor.setBackground(color);
            editor.setForeground(color);
            editor.setText(String.valueOf(newValue));
        } else {
            try {
                Color color = Color.decode(newValue.toString());
                //editor.setBackground(color);
                editor.setForeground(color);
                editor.setText(String.valueOf(newValue));
            } catch (NumberFormatException e) {
            }
        }
    }

    protected void fireActionEvent(Color color) {
        Object listeners[] = listenerList.getListenerList();
        for (int i = listeners.length - 2; i >= 0; i -= 2) {
            if (listeners[i] == ActionListener.class) {
                ActionEvent actionEvent = new ActionEvent(editor, ActionEvent.ACTION_PERFORMED, color.toString());
                ((ActionListener) listeners[i + 1]).actionPerformed(actionEvent);
            }
        }
    }
}

class ColorCellRenderer1 implements ListCellRenderer {

    private DefaultListCellRenderer defaultRenderer = new DefaultListCellRenderer();
    // Width doesn't matter as the combo box will size
    private final static Dimension preferredSize = new Dimension(0, 20);

    @Override
    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
        JLabel renderer = (JLabel) defaultRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
        if (value instanceof Color) {
            //renderer.setBackground((Color) value);
            renderer.setBackground(Color.white);
            renderer.setForeground((Color) value);
        }
        if (cellHasFocus || isSelected) {
            renderer.setBorder(new LineBorder(Color.DARK_GRAY));
        } else {
            renderer.setBorder(null);
        }
        renderer.setPreferredSize(preferredSize);
        return renderer;
    }
}

class ColorComboBoxEditorRendererDemo1 {

    public ColorComboBoxEditorRendererDemo1() {
        Color colors[] = {Color.BLACK, Color.BLUE, Color.GREEN, Color.RED, Color.WHITE, Color.YELLOW};
        JFrame frame = new JFrame("Color JComboBox");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        final JComboBox comboBox = new JComboBox(colors);
        comboBox.setEditable(true);
        comboBox.setRenderer(new ColorCellRenderer1());
        Color color = (Color) comboBox.getSelectedItem();
        ComboBoxEditor editor = new ColorComboBoxEditor1(color);
        comboBox.setEditor(editor);
        frame.add(comboBox, BorderLayout.NORTH);
        final JLabel label = new JLabel();
        label.setOpaque(true);
        label.setBackground((Color) comboBox.getSelectedItem());
        frame.add(label, BorderLayout.CENTER);
        ActionListener actionListener = new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                Color selectedColor = (Color) comboBox.getSelectedItem();
                label.setBackground(selectedColor);
            }
        };
        comboBox.addActionListener(actionListener);
        frame.setSize(300, 200);
        frame.setVisible(true);
    }

    public static void main(String args[]) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                ColorComboBoxEditorRendererDemo1 cCBERD1 = new ColorComboBoxEditorRendererDemo1();
            }
        });
    }
}
+4
source

The foreground text color in your example seems to work correctly. Some other colors are controlled by the component UI delegate for this Look and Feel, as shown below. Please note that the delegate can choose to apply the color in such a way as to maintain contrast in various states, for example, selected, enabled, etc. You can learn more in the article UIManager Default Values .

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

        @SuppressWarnings("synthetic-access")
        public void run() {
            createAndShowGUI();
        }
    });
}
+2
source

Source: https://habr.com/ru/post/1669133/


All Articles