[Java Swing] Customize JList – JList custom renderer

In all JList we know how to create a JList with some simple manipulation and event. In this article we continue to learn how to customize the JList to create a list of elements according to our. For example, phonebook (image, contact name, Phone Number) or a list of favorite books (includes cover, title, the author's name) as shown below:
custom jlist
First let's create a class to store information Book books. In this three-Book class attribute is the name of, author and the title of the book covers the initialization method, getter, setter below:

package nguyenvanquan7826.JList;

public class Book {
	private String name;
	private String author;
	private String iconName;

	public Book(String name, String author, String iconName) {
		super();
		this.name = name;
		this.author = author;
		this.iconName = iconName;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}

	public String getIconName() {
		return iconName;
	}

	public void setIconName(String iconName) {
		this.iconName = iconName;
	}
}

Next we create JFrame displays a list of our book. In JFrame containing a JPanel là main panel, This JPanel containing 1 JList is listBook, listBook placed in 1 JScrollPane to be able to scroll up and down the long list of cases, JList does not display all.

package nguyenvanquan7826.JList;

import java.awt.BorderLayout;

import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.EmptyBorder;

public class JListCustomRenderer extends JFrame {
	private int width = 350;
	private int height = 200;
	private JList<Book> listBook;

	public JListCustomRenderer() {
		// add main panel
		add(createMainPanel());
		// set display
		setTitle("JLIstCustomRenderer");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setSize(width, height);
		setLocationRelativeTo(null);
		setVisible(true);
	}

	private JPanel createMainPanel() {
		JPanel panel = new JPanel(new BorderLayout());
		panel.setBorder(new EmptyBorder(10, 10, 10, 10));
		// create list book and set to scrollpane and add to panel
		panel.add(new JScrollPane(listBook = createListBooks()),
				BorderLayout.CENTER);
		return panel;
	}

	private JList<Book> createListBooks() {
		// create List model
		DefaultListModel<Book> model = new DefaultListModel<>();
		// add item to model
		model.addElement(new Book("C/C++ Programming", "A", "cpp"));
		model.addElement(new Book("Java Programming", "B", "java"));
		model.addElement(new Book("C# Programming", "C", "cs"));
		model.addElement(new Book("IOS Programming", "D", "ios"));
		model.addElement(new Book("Windows Phone Programming", "E", "wp"));
		model.addElement(new Book("Android Programming", "F", "android"));
		// create JList with model
		JList<Book> list = new JList<Book>(model);
		return list;
	}

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

Well done, So we have a list of books and, run program to see what it? It's out this =)) surprise, not desired at all@@

custom jlist

Why such, we have added to the list of books that contain the name and the name of the author, So why the program to display such? Indeed, JList is processed through Model List and further the objects of the JList show performed by an object called Renderer and with each JList it has a default renderer. So the default renderer how this works? Renderer is responsible for displaying the elements in the JList. It is done by calling the method toString() JList object and put in chains get to show up. And by the Book class we did not write threads toString() Renderer should have taken that string toString() default in class Book. And the chain that we get in the program as well as the string on which the system provides for each object in the JList Book.
Now we try to override toString() Book of the following class:

@Override
public String toString() {
	return name + " - " + author;
}

We override toString() to return the name and author of the book. So when you run the program we get a list like this:

custom jlist

It looks like we have seen steady and? No, they must! We need to show the cover as the opening image, it must do so? As we all know the JList is displayed by Renderer then when you want to change it is absolutely easy by rewriting the JList Renderer according to our.
Now let's determine whether each element in what is JList? Here we want it to be a JPanel containing three JLabel, JLabel is a cover photo books, a JLabel JLabel name and last book is the author's name is blue.
To customizable Renderer we will write again another class called BookRenderer inherit from a JPanel. Also this class implements an interface name is required ListCellRenderer. This interface has a method getListCellRendererComponent() return to our main JPanel and it is processed to show up JList.

package nguyenvanquan7826.JList;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.GridLayout;

import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.ListCellRenderer;

public class BookRenderer extends JPanel implements ListCellRenderer<Book> {

	private JLabel lbIcon = new JLabel();
	private JLabel lbName = new JLabel();
	private JLabel lbAuthor = new JLabel();

	public BookRenderer() {
		setLayout(new BorderLayout(5, 5));

		JPanel panelText = new JPanel(new GridLayout(0, 1));
		panelText.add(lbName);
		panelText.add(lbAuthor);
		add(lbIcon, BorderLayout.WEST);
		add(panelText, BorderLayout.CENTER);
	}

	@Override
	public Component getListCellRendererComponent(JList<? extends Book> list,
			Book book, int index, boolean isSelected, boolean cellHasFocus) {

		lbIcon.setIcon(new ImageIcon(getClass().getResource(
				"/nguyenvanquan7826/JList/" + book.getIconName() + ".jpg")));
		lbName.setText(book.getName());
		lbAuthor.setText(book.getAuthor());
		lbAuthor.setForeground(Color.blue);

		return this;
	}
}

Each element in the JList is a JPanel. This is BorderLayout layout JPanel, it contains the Icon in the west (WEST) and panelText. panelText is a JPanel containing two JLabel the title and author's name.
We set the text and icon for the JLabel in methods getListCellRendererComponent(). This method takes an object of class on the book Book TV. The main object of this book is the element in which it is displayed JList. So we put the icon, of the JLabel text through taking iconName, name, author of this book object.
Now we go back and revise JListCustomRenderer class method as follows createListBook:

private JList<Book> createListBooks() {
	// create List model
	DefaultListModel<Book> model = new DefaultListModel<>();
	// add item to model
	model.addElement(new Book("C/C++ Programming", "A", "cpp"));
	model.addElement(new Book("Java Programming", "B", "java"));
	model.addElement(new Book("C# Programming", "C", "cs"));
	model.addElement(new Book("IOS Programming", "D", "ios"));
	model.addElement(new Book("Windows Phone Programming", "E", "wp"));
	model.addElement(new Book("Android Programming", "F", "android"));
	// create JList with model
	JList<Book> list = new JList<Book>(model);
	// set cell renderer 
	list.setCellRenderer(new BookRenderer());
	return list;
}

Now run the program and you will be as desired JList.
custom jlist

However unfinished. Have you noticed that when we click on an item they do not see anything@@phenomenon. That's because we have to rewrite Renderer Renderer default effects that create no more (background color when selected 1 item). We will set the background color for the JPanel, for the JLabel when it is selected or not selected as follows (write the method getListCellRendererComponent() of class BookRenderer)

@Override
public Component getListCellRendererComponent(JList<? extends Book> list,
		Book book, int index, boolean isSelected, boolean cellHasFocus) {

	lbIcon.setIcon(new ImageIcon(getClass().getResource(
			"/nguyenvanquan7826/JList/" + book.getIconName() + ".jpg")));
	lbName.setText(book.getName());
	lbAuthor.setText(book.getAuthor());
	lbAuthor.setForeground(Color.blue);

	// set Opaque to change background color of JLabel
	lbName.setOpaque(true);
	lbAuthor.setOpaque(true);
	lbIcon.setOpaque(true);

	// when select item
	if (isSelected) {
		lbName.setBackground(list.getSelectionBackground());
		lbAuthor.setBackground(list.getSelectionBackground());
		lbIcon.setBackground(list.getSelectionBackground());
		setBackground(list.getSelectionBackground());
	} else { // when don't select
		lbName.setBackground(list.getBackground());
		lbAuthor.setBackground(list.getBackground());
		lbIcon.setBackground(list.getBackground());
		setBackground(list.getBackground());
	}
	return this;
}

That's it, Now we can perform and then select the item.

custom jlist

There is a very small part is that the cover image of the book seems relatively close to each other? do we separated out some beautiful like shape at the top of the article offline, That means you can do (suggested to put lbIcon 1 Empty Border JPanel and set the JPanel that).
The package can be downloaded here Custom Jlist
custom jlist

With reference to the article at: codejava.net