java – What is a good way to make an application selector layout?

I, personally, would start with a JList with a HORIZONTAL_WRAP

See How to Use Lists for more details

For example…

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Image;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;

public class Main {
    public static void main(String[] args) {
        new Main();

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    List<Game> games = new ArrayList<>(Arrays.asList(new Game[]{
                        new Game("Assiassins Creed - Black Flag","/boxart/AssassinsCreedBlackFlag.png"))),
                        new Game("Assiassins Creed - Unit","/boxart/AssassinsCreedUnity.png"))),
                        new Game("Battlefield 3","/boxart/BattleField3.png"))),
                        new Game("BioShock","/boxart/BioShock.png"))),
                        new Game("Borderlands","/boxart/BorderLands.png"))),
                        new Game("Dead standing","/boxart/DeadStanding.png"))),
                        new Game("Dishonored","/boxart/Dishnonored.png"))),
                        new Game("Fallout 4","/boxart/Fallout4.png"))),
                        new Game("Far Cry Primal","/boxart/FarCryPrimal.png"))),
                        new Game("Halflife","/boxart/HalfLife.png"))),
                        new Game("Jedi Fallen Order","/boxart/JediFallenOrde.png"))),
                        new Game("Kings Quest VII","/boxart/KingsQueteVII.png"))),
                        new Game("Leisure Suit Larry in the Land of the Lounge Lizards","/boxart/LSL.png"))),
                        new Game("Mass Effect 2","/boxart/Mass Effect 2.png"))),
                        new Game("Mass Effect 3","/boxart/Mass Effect 3.png"))),
                        new Game("Mass Effect","/boxart/Mass Effect.png"))),
                        new Game("Space Quest IV","/boxart/SpaceQuestIV.png"))),
                        new Game("Tomb Raider","/boxart/TombRaider.png"))),
                        new Game("Zelda - Breath of the wild","/boxart/Zelda.png")))

                    JFrame frame = new JFrame();
                    frame.add(new LaunchPane(games));
                } catch (IOException ex) {
                    Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);


    public class LaunchPane extends JPanel {
        public LaunchPane(List<Game> games) {
            setLayout(new BorderLayout());
            DefaultListModel<Game> model = new DefaultListModel<>();

            JList list = new JList(model);
            list.setCellRenderer(new GameListCellRenderer());

            add(new JScrollPane(list));

    public class GameListCellRenderer extends DefaultListCellRenderer {
        public GameListCellRenderer() {

        public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            if (value instanceof Game) {
                Game game = (Game) value;
                setIcon(new ImageIcon(game.getBoxArt()));
            return this;


    public class Game {
        private String title;
        private Image boxArt;

        public Game(String title, Image boxArt) {
            this.title = title;
            this.boxArt = boxArt;

        public String getTitle() {
            return title;

        public Image getBoxArt() {
            return boxArt;


Now, if you want to customise it a bit more, you could create a fully custom ListCellRenderer for example…

public class GameListCellRenderer extends JPanel implements ListCellRenderer<Game> {

    private static Border EMPTY_BORDER = new EmptyBorder(1, 1, 1, 1);
    private static Border SELECTED_BORDER = new LineBorder(Color.BLUE, 1);

    private Map<Game, String> cachedTitle = new HashMap<>();
    private Map<Game, ImageIcon> cachedIcon = new HashMap<>();

    private JLabel titleLabel;
    private JLabel artboxLabel;

    public GameListCellRenderer() {

        titleLabel = new JLabel();
        artboxLabel = new JLabel();

        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridwidth = gbc.REMAINDER;
        gbc.weightx = 1;
        gbc.fill = gbc.HORIZONTAL;

        add(artboxLabel, gbc);
        add(titleLabel, gbc);

    public Component getListCellRendererComponent(JList<? extends Game> list, Game value, int index, boolean isSelected, boolean cellHasFocus) {
        ImageIcon icon = cachedIcon.get(value);
        if (icon == null) {
            icon = new ImageIcon(value.getBoxArt());
            cachedIcon.put(value, icon);
        String title = cachedTitle.get(value);
        if (title == null) {
            FontMetrics fm = getFontMetrics(titleLabel.getFont());
            title = value.getTitle();

            if (fm.stringWidth(title) > 150) {
                do {
                    title = title.substring(0, title.length() - 1);
                } while (fm.stringWidth(title) > 150);
                title = title.substring(0, title.length() - 3) + "...";
            cachedTitle.put(value, title);

        setBorder(isSelected ? SELECTED_BORDER : EMPTY_BORDER);
        return this;


And without changing anything else, it will produce…

enter image description here

Leave a Comment