Skip to main content

Swing Tutorials: Custom JList 2

The previous tutorial on Custom JList here covers the creation of a simple JList displaying a list of countries. This tutorial introduces the implementation of a custom cell renderer to achieve pretty cool stuff with the JList. Here, the list of countries appear with not just their names, but also their flags. First, we begin by modifying the Country model. We add a variable to hold the name of the country's flag. The flag is added in the same package as the view class. package com. coolcodingtutorials . model ; /** * * @author jaletechs */ public class Country { private String name; private int id; public Country ( int id, String name) { this . name = name; this . id = id; } public String getName () { return name; } public void setName (String name) { this . name = name; } public int getId () { return id; } public void setId ( int id) { this . id = i...

Swing Tutorials: Custom JList 2



The previous tutorial on Custom JList here covers the creation of a simple JList displaying a list of countries. This tutorial introduces the implementation of a custom cell renderer to achieve pretty cool stuff with the JList. Here, the list of countries appear with not just their names, but also their flags.
First, we begin by modifying the Country model. We add a variable to hold the name of the country's flag. The flag is added in the same package as the view class.


package com.coolcodingtutorials.model;

/**
 *
 * @author jaletechs
 */
public class Country {

    private String name;
    private int id;

    public Country(int id, String name) {
        this.name = name;
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 41 * hash + this.id;
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Country other = (Country) obj;
        if (this.id != other.id) {
            return false;
        }
        return true;
    }
    
    @Override
    public String toString(){
        return name;
    }
}




Next, we update the dummy country factory to reflect the constructor change



package com.coolcodingtutorials.model;

import java.util.List;
import java.util.ArrayList;

/**
 *
 * @author jaletechs
 */
public class CountryFactory {
    public static List<Country> getCountries(){
        ArrayList<Country> countries = new ArrayList<>();
        
        countries.add(new Country(1, "Nigeria","nigeria.png"));
        countries.add(new Country(1, "USA","usa.png"));
        countries.add(new Country(3, "Belgium","belgium.png"));
        
        return countries;
    }
}


Note the names of the flag variable are simply strings with the appropriate file
extensions e.g. "nigeria.png". Ensure to put the image files in the same package
as the CountryCellRenderer.java file we would soon examine.
Next, we add the Custom cell renderer (CountryCellRenderer.java)



package com.coolcodingtutorials.view;
import com.coolcodingtutorials.model.Country;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.swing.*;
import javax.swing.border.BevelBorder;

import net.coobird.thumbnailator.Thumbnails;

@SuppressWarnings({ "serial", "rawtypes" })
public class CountryCellRenderer extends JPanel implements ListCellRenderer
{
 private final Color HIGHLIGHT_COLOR = new Color(0,200,255);
 
 private JLabel flag;
 private JLabel name;
  
 public CountryCellRenderer()
 {
  setLayout(new BorderLayout());
  setBorder(new BevelBorder(BevelBorder.LOWERED));
  flag = new JLabel();
  flag.setPreferredSize(new Dimension(65,65));
  flag.setBorder(BorderFactory.createLineBorder(Color.BLACK));
                
                name = new JLabel();
  name.setOpaque(true);
  
  JPanel centerPanel = new JPanel();
  centerPanel.add(name);
  
                add(flag, BorderLayout.WEST);
  add(centerPanel, BorderLayout.CENTER);
 }//end constructor
 
 public Component getListCellRendererComponent(
   JList list,
   Object value,
   int index,
   boolean isSelected,
   boolean hasNextFocus)
 {
  Country country = (Country) value;
  
  //deal with the Item Image
  ImageIcon icon = new ImageIcon(getClass().getResource(country.getImage()));
  BufferedImage bi = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_RGB);
  Graphics g = bi.createGraphics();
  //draw
  icon.paintIcon(null, g, 0, 0);
  g.dispose();
  try {
   BufferedImage thumbnail = Thumbnails.of(bi).size(65,65).asBufferedImage();
   icon = new ImageIcon(thumbnail);
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  
  flag.setIcon(icon);
  name.setText(country.getName());
  
  if(isSelected)
  {
   setOpaque(true);
   setBackground(HIGHLIGHT_COLOR);
   setForeground(Color.WHITE);
   setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
  }
  else
  {
   setOpaque(false);
   setBackground(Color.BLACK);
   setForeground(Color.WHITE);
  }
  return this;
 }//end method getListCellRendererComponent
}//end class CountryCellRenderer

With a few neat tricks, anything is possible when it comes to customizing a JList to your taste. The first thing to consider is the ListCellRenderer interface. With a single method to be overridden, the desired look can be achieved. In our custom cell renderer, we extend the JPanel class and create two labels (type: JLabel) to carry the name of the country and its flag beside it. A custom implementation of the ListCellRenderer just indicates that we have provided our own implementation of what the JList should look like.



package com.coolcodingtutorials.view;

import com.coolcodingtutorials.model.Country;
import com.coolcodingtutorials.model.CountryFactory;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;

/**
 *
 * @author jaletechs
 */
public class MainWindow {
    public static void main(String[] args) {
        MainWindow window = new MainWindow();
        window.go();
    }
    
    private void go(){
        //create a frame
        JFrame frame = new JFrame("Custom JList");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        //create a JList
        JList<Country> jList = new JList(CountryFactory.getCountries().toArray());
        jList.setCellRenderer(new CountryCellRenderer());
        
        //add JList to a Scroll pane
        JScrollPane scroller = new JScrollPane(jList);
        
        frame.getContentPane().add(scroller);
        
        
        frame.setSize(300,300);
        frame.setVisible(true);
    }
}

Now, with just a single line in our view class, we can change the way the JList renders our data: jList.setCellRenderer(new CountryCellRenderer());

Output:
 

Comments

Popular posts from this blog

Swing Tutorials: Custom JList

The JList is a cool swing component that is used to display a list. Unlike a drop down or a JComboBox in swing, a JList displays all of its items at once, allowing the user to scroll in the event that the other items are not visible on the screen. For good UI/UX sometimes, a JList is sometimes the perfect widget for displaying a list of items that could trigger some actions on the UI. So let's get down to it. First we create a custom object. We wish our JList to display a list of countries, so we create a country object as seen below: package com. coolcodingtutorials . model ; /** * * @author jaletechs */ public class Country { private String name; private int id; public Country ( int id, String name) { this . name = name; this . id = id; } public String getName () { return name; } public void setName (String name) { this . name = name; } public int getId () { return id; } public void setId ( int id) { thi...