WinJar #1 - JList e JScrollPane em uma única Classe

Resolvi postar aqui uma classe que criei onde extendo tanto JList quanto JScrollPane pois um depende do outro no meu ponto de vista. Avaliem a Classe e deem sugestões de melhoria.

package acao;

import gen.MeuModelList;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

public abstract class GeraJList extends JScrollPane {

    private MeuJList lista;
    protected MeuModelList modelList;
            
    public GeraJList(int x, int y, int w, int h, List dados, String dica, int [] cor) {
        super(null, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED);
        this.setBounds(x,y,w,h);
        this.setToolTipText(dica);
        lista = new MeuJList(dados, dica, cor);
        lista.addListSelectionListener(new ListSelectionListener() { // Ao navegar pela Lista
            public void valueChanged(ListSelectionEvent e) {
                if(!e.getValueIsAdjusting())
                    getValueChanged(); // Recupera Objeto ?.getJList().getSelectedValue().toString() ou ?.getText
            }
        });
        lista.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() == 2) {
                    getDoubleClick();
                }
            }
        });
        lista.addKeyListener(new KeyListener() {
            @Override  // if (e.getKeyCode() == KeyEvent.VK_F9){}
            public void keyPressed (KeyEvent e) {getKeyPressed(e);}
            public void keyReleased(KeyEvent e) {}
            public void keyTyped   (KeyEvent e) {}
        });
        
        this.setViewportView(lista);
    }
    public GeraJList(int x, int y, int w, int h, List dados, String dica) {this(x, y, w, h, dados, dica, null);}
    public GeraJList(int x, int y, int w, int h, List dados) {this(x, y, w, h, dados, null, null);}
    public GeraJList(int x, int y, int w, int h) {this(x, y, w, h, new ArrayList(), null, null);}
    public GeraJList(int x, int y, int w, int h, String dica) {this(x, y, w, h, new ArrayList(), dica, null);}

/**
 * Retorna o Objeto
 * @return 
 */ public MeuJList getList() {
        return lista;
    } 
/**
 * Retorna toString do Objeto
 * @return 
 */ public String getText  (){
        return lista.getSelectedValue().toString();
    } 
/**
 * Atualiza a lista
 * @param list 
 */ public void atualiza(List list) {
        modelList = (MeuModelList) lista.getModel();
        modelList.atualiza(list);
        lista.repaint();
    }
 
    public void setEditable(boolean altera){
        if (altera){
            this.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        } else {
            this.atualiza(new ArrayList());
            this.setBorder(javax.swing.BorderFactory.createTitledBorder(""));
        }
    }
/**
 * Classe interna do jList
 */ class MeuJList extends javax.swing.JList {
     
        private int [] cor;
        
        public MeuJList(List lista, String dica, int [] cor) {
            this.setToolTipText(dica);
            this.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
            this.setLayoutOrientation(JList.VERTICAL);
            this.cor = cor;
            this.setModel(new MeuModelList(lista));
            this.setSelectedIndex(0);
            this.setCellRenderer(new MeuCellRenderer());
            this.setFont(new Font("Sans Serif", Font.PLAIN, 12));
            if (cor!=null && cor[0]!=0 && cor[1]!=0 && cor[2]!=0) {
                this.setForeground(new java.awt.Color(cor[0], cor[1], cor[2]));
            }
        }        
        public class MeuCellRenderer implements ListCellRenderer {
            protected DefaultListCellRenderer defaultRenderer = new DefaultListCellRenderer();
            protected Color foreground;
            protected Color background;
            @Override
            public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
                JLabel renderer = (JLabel) defaultRenderer.getListCellRendererComponent(list, value, index,isSelected, cellHasFocus);
             // Altera a Cor
                if (cor!=null && cor.length>=6) {
                    if (isSelected) {
                        foreground = Color.getHSBColor(cor[0],cor[0],cor[0]);
                        background = Color.getHSBColor(cor[1],cor[1],cor[1]);
                    } else {
                        if (index % 2 == 0) {
                            foreground = Color.getHSBColor(cor[2],cor[2],cor[2]);
                            background = Color.getHSBColor(cor[3],cor[3],cor[3]);
                        } else {
                            foreground = Color.getHSBColor(cor[4],cor[4],cor[4]);
                            background = Color.getHSBColor(cor[5],cor[5],cor[5]);
                        }
                    }
                    renderer.setForeground(foreground);
                    renderer.setBackground(background);
                }
                return renderer;
            }        
        }
    }
  // Métodos abstratos
    public abstract void getValueChanged (); 
    public abstract void getDoubleClick (); 
    public abstract void getKeyPressed (KeyEvent e); 
}

Alguns Métodos a serem comentado

  • getList() - Retorna o JList já que a classe principal é o JScrollPane
  • getText() - Retorna toString do Objeto. Geralmente eu reescrevo o toString das classes que vão me retornar um ArrayList
  • atualiza(List list) - Passo um novo “List” para atualizar o JList. chamo este método quando faço CRUD.

AbstractListModel

package acao;

import java.util.List;
import javax.swing.AbstractListModel;
/**
 * Model do meu JList
 * @author vonquelbe.caldeira
 */
public class MeuModelList extends AbstractListModel {
    
    private List lista;
 // Construtor
    public MeuModelList(List lista) {
        this.lista = lista;
    }
    @Override
    public int getSize() {return lista.size();}
    @Override
    public Object getElementAt(int index) {return lista.get(index);}
    
    public void atualiza(List lista){
        this.lista = lista;
        this.fireContentsChanged(this, 0, lista.size());
    }
 // Outros --------------------------------------------------

    public void addElement(Object obj) {
        lista.add(obj);
        this.fireIntervalAdded(obj, this.getSize() - 1, this.getSize() - 1);
    }
    public void removeElement(Object obj) {
        this.fireIntervalRemoved(obj, lista.indexOf(obj), lista.indexOf(obj));
        lista.remove(obj);
    }
    public void insertElementAt(Object obj, int index) {
        lista.add(index, obj);
        this.fireIntervalAdded(obj, index, index);
    }
    public void removeElementAt(int index) {
        this.fireIntervalRemoved(lista.get(index), index, index);
        lista.remove(index);

    }

    public void print() {
        System.out.println("\nLista");
        for (int i = 0; i < this.lista.size(); i++) {
            System.out.println(this.lista.get(i));
        }
    }    
        
}

Executando

package acao;

import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;

public class Inicio {
    
    private static javax.swing.JFrame tela;
    private static GeraJList lista;
    
    public static void main(String[] args) {
        
        List <Object> obj = new ArrayList();
        obj.add("Java");
        obj.add("Oracle");
        obj.add("Delphi");
        obj.add("C#");
        obj.add("C++");
        obj.add("MySQL");
        
        tela = new javax.swing.JFrame("Testando GeraJList");
        tela.setSize(300,150);
        tela.setResizable(false);
        tela.setLocationRelativeTo(null);
        tela.setDefaultCloseOperation(3);
        tela.setLayout(null);
        
        lista = new GeraJList(10,10,200,74, obj) {
            @Override
            public void getValueChanged() {
                System.out.println("Selecionado: "+lista.getText());
            }
            @Override
            public void getDoubleClick() {
                System.out.println("Duplo Click");
            }
            @Override
            public void getKeyPressed(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_F9){
                    System.out.println("Clicou no F9");
                }
            }
        };
        tela.add(lista);        
        tela.setVisible(true);
    }
}

Neste exemplo usei o Object com String mas pode ser usado qualquer ArrayList. Eu geralmente uso de uma classe.

OBS: Coloquei três métodos Abstratos na classe que tem a função de facilitar a minha vida. Esses métodos são chamados quando a lista é percorrida, ao dar um duplo click na lista ou quando uma tecla for chamada (F1 a F12 por exemplo). Caso não interesse, basta comentar.

image