Colored jcombobox with colored items and focus

后端 未结 3 802
滥情空心
滥情空心 2021-01-03 10:18

i am trying to make a colored dropdown list with colored items (please see code below). The color is getting applied after the combobox loses focus.

is this correct

相关标签:
3条回答
  • 2021-01-03 10:31

    please split Editor and Renderer, and add to DefaultListCellRenderer these two methods

    • 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();
                }
            });
        }
    }
    
    0 讨论(0)
  • 2021-01-03 10:37

    The foreground text colors in your example seem to work correctly. Certain other colors are managed by the component's UI delegate for a given Look & Feel, as shown below. Note that the delegate may choose to apply a color in a way that preserves contrast in various states, e.g selected, enabled, etc. You can learn more in the article UIManager Defaults.

    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();
            }
        });
    }
    
    0 讨论(0)
  • 2021-01-03 10:53

    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);
      }
    }
    
    0 讨论(0)
提交回复
热议问题