Search code examples
javaswingcolorsjlist

Change JList item colour when I want


I'm trying to build a JList in which some of the items have a different background colour than others but only when I want it.

I've been trying to do something like this up it produces errors.

 static DefaultListModel<String> model = new DefaultListModel<>();

 for(int K=0;K<Collectionsize();K++){
        Jlist.setForeground(Color.red); 
        model.addElement(type 1);

        for(int I=0;I<(subcollection.size();I++){
            Jlist.setForeground(Color.white); 
            model.addElement(type 2);
            }
        }

There is no pattern between type 1 and 2 so I want change the colour when I want it rather than rely on if statements.

I see a lot of people talking about building custom render classes but I was aiming some something more simple.


Solution

  • Note: A list of items containing two pieces of information per item is better suited to being displayed in a table rather than a list, though you might adapt this to a list if needed. The same basic principle applies (use a rendering component).

    This is what I mean:

    enter image description here

    Which is achieved by this rendering class:

    class TrackCellRenderer extends DefaultTableCellRenderer {
    
        HashMap<String, Color> colorMap = new HashMap<>();
        Random r = new Random();
    
        @Override
        public Component getTableCellRendererComponent(
                JTable table,
                Object value,
                boolean isSelected, boolean hasFocus,
                int row, int column) {
            Component c = super.getTableCellRendererComponent(
                    table, value, isSelected, hasFocus, row, column);
            JLabel l = (JLabel) c;
    
            String s = (String) value;
            if (column == 0) {
                if (!colorMap.containsKey(s)) {
                    Color clr = new Color(
                            150 + r.nextInt(105),
                            150 + r.nextInt(105),
                            150 + r.nextInt(105));
                    colorMap.put(s, clr);
                }
                Color color = colorMap.get(s);
                l.setBackground(color);
                l.setOpaque(true);
            } else {
                l.setOpaque(false);
            }
    
            return l;
        }
    }
    

    Note: it might be best to use an enum rather than randomly assigning a color, but with 3 albums and over a million possible colors, we should be pretty safe.

    In this (two class) MCVE of just over 100 lines of code:

    import java.awt.*;
    import javax.swing.*;
    import javax.swing.border.EmptyBorder;
    import javax.swing.table.*;
    import java.util.*;
    
    public class AlbumTrackTable {
    
        private JComponent ui = null;
        String[][] playList = {
            {"The Will to Live", "Faded"},
            {"The Will to Live", "Homeless Child"},
            {"Oh Mercy", "Political Wrold"},
            {"Oh Mercy", "What Was it You Wanted?"},
            {"Red Sails in the Sunset", "Helps Me Helps You"},
            {"Red Sails in the Sunset", "Redneck Wonderland"}
        };
        String[] columnNames = {"Album", "Track"};
    
        AlbumTrackTable() {
            initUI();
        }
    
        public void initUI() {
            if (ui != null) {
                return;
            }
    
            ui = new JPanel(new BorderLayout(4, 4));
            ui.setBorder(new EmptyBorder(4, 4, 4, 4));
    
            DefaultTableModel trackModel = new DefaultTableModel(playList, columnNames);
            JTable table = new JTable(trackModel);
            ui.add(new JScrollPane(table));
            TableCellRenderer renderer = new TrackCellRenderer();
            table.setDefaultRenderer(Object.class, renderer);
            table.setAutoCreateRowSorter(true);
        }
    
        public JComponent getUI() {
            return ui;
        }
    
        public static void main(String[] args) {
            Runnable r = new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (Exception useDefault) {
                    }
                    AlbumTrackTable o = new AlbumTrackTable();
    
                    JFrame f = new JFrame(o.getClass().getSimpleName());
                    f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                    f.setLocationByPlatform(true);
    
                    f.setContentPane(o.getUI());
                    f.pack();
                    f.setMinimumSize(f.getSize());
    
                    f.setVisible(true);
                }
            };
            SwingUtilities.invokeLater(r);
        }
    }
    
    class TrackCellRenderer extends DefaultTableCellRenderer {
    
        HashMap<String, Color> colorMap = new HashMap<>();
        Random r = new Random();
    
        @Override
        public Component getTableCellRendererComponent(
                JTable table,
                Object value,
                boolean isSelected, boolean hasFocus,
                int row, int column) {
            Component c = super.getTableCellRendererComponent(
                    table, value, isSelected, hasFocus, row, column);
            JLabel l = (JLabel) c;
    
            String s = (String) value;
            if (column == 0) {
                if (!colorMap.containsKey(s)) {
                    Color clr = new Color(
                            150 + r.nextInt(105),
                            150 + r.nextInt(105),
                            150 + r.nextInt(105));
                    colorMap.put(s, clr);
                }
                Color color = colorMap.get(s);
                l.setBackground(color);
                l.setOpaque(true);
            } else {
                l.setOpaque(false);
            }
    
            return l;
        }
    }