Bonjour à tous,
Je développe une application Java/MySQL en essayant de respecter la norme MVC.
Je rencontre quelques petites difficultés avec cette architecture, notamment dans l'utilisation des JTable. Je vais donner un exemple en détail de mon code pour vous expliquer les problèmes que je rencontre.
Pour commencer la Vue, qui affichera une liste de PERSONNE dans une JTable, un bouton pour supprimer une personne, un bouton pour ajouter une personne et un label pour afficher une erreur éventuelle (ex : échec de connection a la base de donnée).
Ensuite les modèles, une classe personne (nom et age) et une classe héritant de AbstractTableModel étant le modèle de la JTable.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 public class ViewPersonne implements ActionListener { private ControlPersonne control; private ModelPersonne model; private JTable tblPersonne; private JButton btnNewPersonne; private JButton btnDelPersonne; private JLabel lblError; public ViewPersonne(ControlPersonne control, ModelPersonne model) { super(); this.control = control; this.model = model; this.tblPersonne = new JTable(model); this.btnNewPersonne = new JButton(); this.btnDelPersonne = new JButton(); this.lblError = new JLabel(); } public void setTextError(String error) { this.lblError.setText(error); this.lblError.repaint(); } ... @Override public void actionPerformed(ActionEvent ev) { if (ev.getSource() == btnNewPersonne) { control.NewPersonne(); } else if (ev.getSource() == btnDelPersonne) { control.deletePersonne(); } }
Je me pose une question par rapport à ce AbstractTableModel , fait il partie de ma vue parcequ'il est développé pour fonctionner avec la JTable, ou fait il partie de mon Modèle ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
105
106
107
108
109
110
111
112
113
114 public class PersonneTableModel extends AbstractTableModel { private String[] title; private ArrayList<PersonneModel> listPersonne; public PersonneTableModel() { super(); this.title = new String[] { "NOM", "AGE" }; this.listPersonne = new ArrayList<PersonneModel>(); } @Override public String getColumnName(int col) { return title[col]; } @Override public int getColumnCount() { return title.length; } @Override public int getRowCount() { return listPersonne.size(); } @Override public Class<?> getColumnClass(int columnIndex) { switch (columnIndex) { case 0: return String.class; case 1: return Integer.class; default: return Object.class; } } @Override public Object getValueAt(int row, int col) { PersonneModel personne = listPersonne.get(row); switch (col) { case 0: return personne.getNom(); case 1: return personne.getAge(); default: return null; } } @Override public boolean isCellEditable(int rowIndex, int columnIndex) { return true; //Toutes les cellules éditables } @Override public void setValueAt(Object aValue, int rowIndex, int columnIndex) { if(aValue != null){ PersonneModel personne = listPersonne.get(rowIndex); String value = aValue.toString(); switch(columnIndex){ case 0: personne.setNom(value); break; case 1: personne.setAge(Integer.parseInt(value)); break; } fireTableCellUpdated(rowIndex, columnIndex); } } public void setListPersonne(ArrayList<PersonneModel> listPersonne) { // efface les items de la liste int lastIndex = getRowCount() - 1; if (lastIndex >= 0) { this.listPersonne.clear(); fireTableRowsDeleted(0, lastIndex); } // ajoute les items à la liste if (listPersonne != null && listPersonne.size() > 0) { for (PersonneModel p : listPersonne) { addPersonne(p); } } } public void addPersonne(PersonneModel personne) { int index = getRowCount; listPersonne.add(index, personne); fireTableRowsInserted(index, index); } public void removePersonne(PersonneModel personne) { int index = listPersonne.indexOf(personne); if (index >= 0) { listPersonne.remove(index); fireTableRowsDeleted(index, index); } } }
Pour terminer mon controller et pour exemple la méthode supprimer personne, le controller tentera de supprimer la personne sélectionné dans la base de données et si la suppression est OK, il supprimera la personne de la JTable par l'intermédiaire de son modèle sinon il affichera l'erreur dans un label de la View.
Cette façon de procéder me permet de capter les erreurs SQL éventuelles avant de supprimer la ligne dans la JTable.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 public void deletePersonne () { try { PersonneModel personne = model.getPersonneSelected(); // Ici un modèle statique permettant d'effectuer les requête SQL sur la table Personne PersonneRequest.deletePersonne(dataBase.getConnection(), personne); dataBase.commitDatas(); // le modele informera la vue de la suppression model.removePersonne(personne); view.setTextError(""); } catch (SQLException e) { // si erreur prévient la vue view.setTextError(e.getMessage()); } catch (Exception e) { // si erreur prévient la vue view.setTextError(e.getMessage()); } }
Je rencontre un problème pour l'édition et la mise à jour d'une cellule en base de données. J'utilise une classe editor héritant de la classe DefaultCellEditor. Une fois la modification effectuée, la méthode setValueAt du modèle de la table (décrit plus haut) est appelée. Mon problème ici est que la cellule sera mise à jour dans la JTable avant de l'être dans ma base de données.
Pour palier ce problème je pourrai faire ma requête SQL directement dans la méthode setValueAt mais si il y a une erreur, je ne sais pas comment l'afficher dans la vue.
De plus je souhaite faire toutes les requêtes SQL depuis mon controller, pour que celui ci puisse interagir avec la vue comme il le souhaite.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 public class PersonneTableModel extends AbstractTableModel { private String[] title; private ArrayList<PersonneModel> listPersonne; ... @Override public void setValueAt(Object aValue, int rowIndex, int columnIndex) { if(aValue != null){ try { PersonneModel personne = listPersonne.get(rowIndex); String value = aValue.toString(); switch(columnIndex){ case 0: personne.setNom(value); break; case 1: personne.setAge(Integer.parseInt(value)); break; } // Ici un modèle statique permettant d'effectuer les requête SQL sur la table Personne PersonneRequest.updatePersonne(dataBase.getConnection(), personne); dataBase.commitDatas(); fireTableCellUpdated(rowIndex, columnIndex); } catch (SQLException e) { // si erreur on ne connait pas le label erreur de la vue } catch (Exception e) { // si erreur on ne connait pas le label erreur de la vue } } } ... }
Sinon je pourrai donner la référence de mon controller au modèle de la table mais cela ne respecterai plus la norme MVC et rendrait le modèle dépendant du controller.
J'ai mis beaucoup de code ici en espérant qu'il puisse servir à quelques un et pour avoir votre avis sur cette façon de procéder.
Vos idées sur mon problème de conception sont les bienvenues.
Merci





Répondre avec citation

Partager