1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
| public class JTableCombo {
public static void main(String[] args) {
JFrame frame = new JFrame("Démo"); // création de la fenêtre
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // lorsqu'on clique sur la "croix", on quitte l'application
frame.add(new JScrollPane(createJTable())); // on créé la JTable, qu'on met dans un scrollpane, qu'on met au centre de la fenêtre
// affichage de la fenêtre en 400x400 centrée dans l'écran
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private static Component createJTable() {
// des données
Object[][] data = { { 1, "toto", "machin" },
{ 2, "toto", "truc" },
{ 3, "toto", "bidule" } };
// les titres des colonnes
String[] cols = { "id","nom","valeur" };
// création d'une JTable simple avec les données et colonnes définies ci-dessus
JTable table = new JTable(data,cols);
ComboCellEditor comboCellEditor = new ComboCellEditor(); // je créé une instance de ma classe de rendu/éditeur
table.getColumnModel().getColumn(2).setCellRenderer(comboCellEditor); // je l'affecte à la colonne 3 en tant que composant de rendu
table.getColumnModel().getColumn(2).setCellEditor(comboCellEditor); // je l'affecte à la colonne 3 en tant qu'éditeur
table.setSurrendersFocusOnKeystroke(true); // nécessaire pour avoir la combo qui passe en édition quand on commence à taper
table.setRowHeight(table.getRowHeight()+3); // truc en dur pour améliorer la préz...mais devrait être générique
return table;
}
/**
* Cette classe combine la notion d'éditeur sous forme de combo et de renderer sous forme de combo
* On utilise un DefaultCellEditor qui a déjà toute la mécanique pour gérer un TableCellEditor de type combo
*/
public static class ComboCellEditor extends DefaultCellEditor implements TableCellRenderer {
private JComboBox<String> combo;
public ComboCellEditor() {
super(new JComboBox<>()); // on créé le DefaultCellEditor en lui passant la combo
combo=(JComboBox<String>) getComponent(); // je récupère la combo passé dans le constructeur juste avant parce que je vais avoir besoin de travailler avec plus tard (je la stocke dans un attribut donc)
// combo.setEditable(true); // éventuellement pour rendre la saisie libre (ici on peut aussi ajouter l'autocompletion)
combo.addFocusListener(new FocusAdapter() { // j'enregistre un focuslistener qui va réagir quand la combo prend le focus pour ouvrir automatiquement la liste de la combo (dès qu'on va commencer à taper dans le champ, la combo va passer en édition et donc afficher la liste déroulante)
@Override
public void focusGained(FocusEvent arg0) {
combo.setPopupVisible(true);
}
});
super.setClickCountToStart(1); // je réduis le nombre de clic pour passer en édition à 1 (par défaut dans une JTable, c'est 2, d'où le besoin de double-cliquer)
}
// méthode de TableCellEditor destinée à créer le composant éditeur qui sera utilisé pour modifier la valeur de la cellule en cours d'édition dans la JTable
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row,
int column) {
combo.setModel(new DefaultComboBoxModel<>(loadValues((Integer)table.getModel().getValueAt(row, 0)))); // je remplis la combo avec un nouveau modèle contenant le résultat de ma requête
if ( isSelected ) { // pour afficher la combo sélectionnée quand la cellule est séctionnée
combo.setBackground(table.getSelectionBackground());
}
else { // sinon je l'affiche dans la couleur normal
combo.setBackground(table.getBackground());
}
return super.getTableCellEditorComponent(table, value, isSelected, row, column); // je rappelle la méthode normale qui va se charger du reste du rendu de l'éditeur
}
// méthode de TableCellRenderer destinée à créer le composant qui affiche la valeur dans la colonne
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
JComboBox<String> renderCombo = new JComboBox<>(new DefaultComboBoxModel<>(new String[]{(String)value})); // je créé une nouvelle combo avec juste une valeur pour faire un rendu qui ressemble à un éditeur
// ici, normalement on doit faire tout le rendu standard, en fonction de isSelected et hasFocus (ici, seul selected est traité)
if ( isSelected ) {
renderCombo.setBackground(table.getSelectionBackground());
}
else {
renderCombo.setBackground(table.getBackground());
}
return renderCombo;
}
}
public static String[] loadValues(int value) {
// ici tu remplaces par ta requête
switch(value) {
case 1:
return new String[]{"machin","machin1","machin2"};
case 2:
return new String[]{"truc","truc1","truc2"};
case 3:
return new String[]{"bidule","bidule1","bidule2"};
}
return null;
}
} |
Partager