Ben Hay
Ben Hay

Reputation: 19

Using ListCellRenderers on selected entries

I'm using a ListCellRenderer to edit the appearance of entries in a JList. Once they are selected (by clicking them, this code is within a click event) I call the ListCellRenderer to change the color of the text. If they are selected again I want the text to return to the normal color. The problem I am having is that once I select a second entry the first entry goes back to its normal color. How can I keep selected entries the selected color until they are actually deselected? Here is the section where I actually call the function:

for(int i = 0; i < selectedEntries.size() - 1; i++){
    System.out.println("Inside the for loop at entry:" + i);
    if(selectedEntries.get(i).equals(selectedEntry)){
        selectedEntries.remove(i);
        removed = true;
        renderer.getListCellRendererComponent(logEntries, value, index, false, false);
        System.out.println("Duplicate Entry Removed From List");
    }
}

if(!removed){
    selectedEntries.add(selectedEntry);
    renderer.getListCellRendererComponent(logEntries, value, index, true, false);
}

Just for ease of interpretation selectedEntries is an ArrayList containing each selected entry's text.

Upvotes: 0

Views: 703

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347332

Once they are selected (by clicking them, this code is within a click event) I call the ListCellRenderer to change the color of the text

No, that's not how it should work, the ListCellRenderer will be called again (by the JList) and the isSelected parameter will be true, to which you would render the values differently

The ListCellRenderer is responsible for rendering the entire state, selected or not selected.

Have a look at Writing a Custom Cell Renderer for more details

For example

List of stuff

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new BorderLayout());
            DefaultListModel<String> model = new DefaultListModel<>();
            model.addElement("Apples");
            model.addElement("Bananas");
            model.addElement("Peachs");
            model.addElement("Pears");
            JList<String> listOfStrings = new JList<>(model);
            listOfStrings.setCellRenderer(new FancyPancyListCellRenderer());
            add(new JScrollPane(listOfStrings));
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

    public static class FancyPancyListCellRenderer  extends DefaultListCellRenderer {

        protected static final Font SELECTED_FONT = new Font("Comic Sans MS", Font.PLAIN, 12);

        @Override
        public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {

            super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            if (isSelected) {
                setForeground(Color.YELLOW);
                setFont(SELECTED_FONT);
            } else {
                setFont(UIManager.getFont("Label.font"));
            }
            return this;

        }

    }

}

Also, MouseListener really isn't a suitable means by which to detect changes in the selection, what happens if the user selects rows using the keyboard? You should be using a ListSelectionListener instead (but not to correct this issue).

Have a look at How to Write a List Selection Listener and How to Use Lists for more details

Upvotes: 3

Related Questions