IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Composants Java Discussion :

[JTable] DefaultTableModel et JTree


Sujet :

Composants Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Novembre 2003
    Messages
    142
    Détails du profil
    Informations forums :
    Inscription : Novembre 2003
    Messages : 142
    Par défaut [JTable] DefaultTableModel et JTree
    Bonjour,

    Je dispose d'une fenêtre avec une JTree sur la gauche et d'une JTable sur la droite.
    Lorsque je clique sur un noeud, le contenu de la jtable change.
    Pour cela, j'ai étendu la classe DefaultTableModel et en fonction du noeud sur lequel j'ai cliqué, je charge les données à partir d'une base d'une donnée dans mon TableModel.

    Pour éviter d'effectuer à chaque fois des requêtes dans la base, je stocke les données correspondant aux différents noeuds dans une collection dans mon TableModel et puis je m'occupe de les afficher et je rafraîchis la JTable à l'aide de fireTableDataChanged.

    Pouvez-vous me dire s'il s'agit d'une bonne pratique ?

  2. #2
    Membre Expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Par défaut
    Citation Envoyé par speedster
    Bonjour,

    Je dispose d'une fenêtre avec une JTree sur la gauche et d'une JTable sur la droite.
    Lorsque je clique sur un noeud, le contenu de la jtable change.
    Pour cela, j'ai étendu la classe DefaultTableModel et en fonction du noeud sur lequel j'ai cliqué, je charge les données à partir d'une base d'une donnée dans mon TableModel.

    Pour éviter d'effectuer à chaque fois des requêtes dans la base, je stocke les données correspondant aux différents noeuds dans une collection dans mon TableModel et puis je m'occupe de les afficher et je rafraîchis la JTable à l'aide de fireTableDataChanged.

    Pouvez-vous me dire s'il s'agit d'une bonne pratique ?
    Oui, si tu as bien fait attention aux threads...
    J'imagine que tu charges dans la base de données à partir d'un thread utilisateur, et il faut que tu fasses le fireTableDataChanged dans l'EDT...

    J'ai justement écrit il y a quelques jours un article sur les modèles, ça concerne plus les ListModel mais c'est valable pour TableModel également...
    http://rom.developpez.com/java-swingui-models.pdf

  3. #3
    Membre confirmé
    Inscrit en
    Novembre 2003
    Messages
    142
    Détails du profil
    Informations forums :
    Inscription : Novembre 2003
    Messages : 142
    Par défaut
    Il s'agit d'un client lourd donc appli monothread.

    Je me demande par contre s'il n'est pas plus judicieux de faire une requête à chaque fois dans la base de données en utilisant le cache des requêtes avec Hibernate (moins de code dans le TableModel) mais là je sors du thème de ce forum.

  4. #4
    Membre chevronné Avatar de Claythest
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    558
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 558
    Par défaut
    Citation Envoyé par speedster
    Il s'agit d'un client lourd donc appli monothread.
    Justement non !

    Client lourd = multi thread

    http://rom.developpez.com/java-swingworker/

    Ensuite, les données de ta base de données peuvent elles etres modifiée en dehors de ton programme JAVA ?

    Si non, alors il te suffit de stocker le résultat de chaque requetes, et de charger depuis la BD uniquement quand on t'en demande une nouvelle (avec peut être aussi gestion d'une taille limite / nombre de résultats de requêtes stockées pour ton cache).

    Si oui, alors c'est plus compliqué de gérer un cache, puisque tu sauras difficilement si ton cache est à jour ou non...

  5. #5
    Membre confirmé
    Inscrit en
    Novembre 2003
    Messages
    142
    Détails du profil
    Informations forums :
    Inscription : Novembre 2003
    Messages : 142
    Par défaut
    Citation Envoyé par Claythest
    Justement non !

    Client lourd = multi thread

    http://rom.developpez.com/java-swingworker/
    Merci beaucoup pour cette précision. Je me retrouve bête là

    Le fireTableDataChanged est appelé dans la méthode qui fait appel à la requête.

    Dans ma classe qui étend le DefaultTableModel, j'ai une méthode que j'ai appelé setModel() dans laquelle je fais appel à ma requête puis le fireTableDataChanged.

    Je ne sais pas distinguer le thread utilisateur de l'edt

    Je gère un cache et j'utilise le pattern observateur. Les modifs ne sont faites que dans le programme. A ce moment, je lance un update qui fait à nouveau appel à la requête sinon il s'agit d'un simple affichage.

    Mais je me demandais s'il n'était pas plus judicieux de laisser hibernate gérer le cache à l'aide du cache de second niveau (cache des requêtes).


    Dans mon implémentation, la classe interne MatchCase représente le type d'objet mis en cache.

    Voici le code d'un de mes modèles :
    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
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    public class MatchesTableModel extends GenericNonEditableTableModel implements
    		MatchUpdateListener, MatchInsertionListener {
     
    	/**
             * 
             */
    	private static final long serialVersionUID = -3466645481527750345L;
     
    	public static final int COLONNE_MATCH = 8;
     
    	private boolean displaying;
     
    	private InfosChampionnat infosChampionnat;
     
    	private Match sourceMatch;
     
    	private int typeClassementAffiche; // par défaut classement général
     
    	private boolean matchesParUtilisateur; // par défaut à faux
     
    	private boolean matchesJoues = true; // par défaut à vrai
     
    	private boolean matchesAJouer = true;  // par défaut à vrai
     
    	private UtilisateurParticipant uP;
     
    	private List<MatchCase> allDataVectors = new ArrayList<MatchCase>();
     
    	private class MatchCase {
    		private boolean toUpdate = false;
    		private InfosChampionnat infosChampionnat;
    		private List<Match> allMatches;
     
    		/**
                     * @param infosChampionnat
                     */
    		public MatchCase(InfosChampionnat infosChampionnat) {
    			super();
    			this.infosChampionnat = infosChampionnat;
    		}
     
    		public List<Match> getAllMatches() {
    			return allMatches;
    		}
     
    		public void setAllMatches(List<Match> allMatches) {
    			this.allMatches = allMatches;
    		}
     
    		public boolean isToUpdate() {
    			return toUpdate;
    		}
     
    		public void setToUpdate(boolean toUpdate) {
    			this.toUpdate = toUpdate;
    		}
     
    		@Override
    		public int hashCode() {
    			final int PRIME = 31;
    			int result = 1;
    			result = PRIME * result + ((infosChampionnat == null) ? 0 : infosChampionnat.hashCode());
    			return result;
    		}
     
    		@Override
    		public boolean equals(Object obj) {
    			if (this == obj)
    				return true;
    			if (obj == null)
    				return false;
    			if (getClass() != obj.getClass())
    				return false;
    			final MatchCase other = (MatchCase) obj;
    			if (infosChampionnat == null) {
    				if (other.infosChampionnat != null)
    					return false;
    			} else if (!infosChampionnat.equals(other.infosChampionnat))
    				return false;
    			return true;
    		}
    	}
     
    	/**
             * 
             */
    	public MatchesTableModel() {
    		setColumnIdentifiers();
    	}
     
    	@SuppressWarnings("unchecked")
    	private void setColumnIdentifiers() {
    		columnIdentifiers.add("");
    		columnIdentifiers.add("Journée");
    		columnIdentifiers.add("Domicile");
    		columnIdentifiers.add("");
    		columnIdentifiers.add("Vs.");
    		columnIdentifiers.add("");
    		columnIdentifiers.add("Extérieur");
    		columnIdentifiers.add("");
    	}
     
    	private Vector toVector(Match match) {
    		Vector<Object> ligne = new Vector<Object>();
    		ligne.addElement(match.getForfait());
    		ligne.addElement(match.getJournee());
    		ligne.addElement(match.getHomeUser());
    		ligne.addElement(match.getNbButs1());
    		ligne.addElement("-");
    		ligne.addElement(match.getNbButs2());
    		ligne.addElement(match.getAwayUser());
    		ligne.addElement(match.getVerrouille());
    		ligne.addElement(match);
    		return ligne;
    	}
     
    	@SuppressWarnings("unchecked")
    	private Vector filterMatches(List<Match> allMatches) {
     
    		Vector newDataVector = new Vector();
     
    		for (Match match : allMatches) {
    			// filtrer matches à jouer
    			if (!matchesJoues && matchesAJouer) {
    				if (match.getNbButs1() == null && match.getNbButs2() == null);
    				else continue;
    			}
    			// filtrer matches joués
    			else if (matchesJoues && !matchesAJouer) {
    				if (match.getNbButs1() != null && match.getNbButs2() != null);
    				else continue;
    			}
    			// matches joués et à jouer : pas de filtre
     
    			// filtre matches par utilisateur
    			if (matchesParUtilisateur) {
    				if (match.getUtilisateurParticipantByNumUtilisateurParticipant1().equals(uP)
    					|| match.getUtilisateurParticipantByNumUtilisateurParticipant2().equals(uP)) {
     
    					// classement général : pas de filtre
     
    					// classement à domicile
    					if (typeClassementAffiche == PescorerConstants.TYPE_CLASSEMENT_DOMICILE) {
    						if (match.getUtilisateurParticipantByNumUtilisateurParticipant1().equals(uP));
    						else continue;
    					}
    					// classement à l'extérieur
    					else if (typeClassementAffiche == PescorerConstants.TYPE_CLASSEMENT_EXTERIEUR) {
    						if (match.getUtilisateurParticipantByNumUtilisateurParticipant2().equals(uP));
    						else continue;
    					}
    				}
    				else continue;
    			}	
    			// matches de tous les utilisateurs : pas de filtre
     
    			// ajout du match
    			newDataVector.addElement(toVector(match));
    		}
    		return newDataVector;
    	}
     
    	private List<Match> loadAllMatches() {
    		MatchService matchService = (MatchService) PescorerApplicationContext.getInstance().getBean("matchService");
    		List<Match> allMatches = matchService.findMatchesByInfosChampionnat(infosChampionnat);
     
    		dataVector = filterMatches(allMatches);
     
    		fireTableDataChanged();
     
    		return allMatches;
    	}
     
    	private void setModel() {
    		MatchCase mCase = new MatchCase(infosChampionnat);
    		int idx = allDataVectors.indexOf(mCase);
    		if (idx != -1) {
    			MatchCase realMCase = allDataVectors.get(idx);
    			List<Match> allMatches = realMCase.getAllMatches();
    			if (allMatches != null) {
    				dataVector = filterMatches(allMatches);
    				fireTableDataChanged();
    			}
    			else {
    				realMCase.setAllMatches(loadAllMatches());
    				realMCase.setToUpdate(false);
    			}
    		}
    		else {
    			mCase.setAllMatches(loadAllMatches());
    			allDataVectors.add(mCase);
    			mCase.setToUpdate(false);
    		}
    	}
     
    	private void setModelUpdated() {
    		MatchCase mCase = new MatchCase(infosChampionnat);
    		int idx = allDataVectors.indexOf(mCase);
     
    		MatchCase realMCase = allDataVectors.get(idx);
    		realMCase.setAllMatches(loadAllMatches());
     
    		realMCase.setToUpdate(false);
    	}
     
    	public boolean isToUpdate() {
    		MatchCase mCase = new MatchCase(infosChampionnat);
    		int idx = allDataVectors.indexOf(mCase);
     
    		MatchCase realMCase = allDataVectors.get(idx);
    		return realMCase.isToUpdate();
    	}
     
    	public void setSource(Match match) {
    		this.sourceMatch = match;
    	}
     
    	public void setToUpdate(boolean toUpdate) {
    		InfosChampionnat infos = new InfosChampionnat(sourceMatch.getTournoi(), sourceMatch.getGroupe());
    		MatchCase mCase = new MatchCase(infos);
    		int idx = allDataVectors.indexOf(mCase);
    		// déjà existant
    		if (idx != -1) {
    			MatchCase realMCase = allDataVectors.get(idx);
    			realMCase.setToUpdate(toUpdate);
    		}
    		// n'existe pas encore
    		else {
    			mCase.setToUpdate(toUpdate);
    			allDataVectors.add(mCase);
    		}
    		this.infosChampionnat = infos;
    	}
     
    	public void update() {
    		if (isToUpdate()) {
    			setModelUpdated();
    		}
    	}
     
    	public void setModel(InfosChampionnat infosChampionnat, int selectedIndex, 
    			boolean matchesParUtilisateur, boolean matchesJoues, boolean matchesAJouer, UtilisateurParticipant uP) {
    		this.infosChampionnat = infosChampionnat;
    		this.setSelections(selectedIndex, matchesParUtilisateur, matchesJoues, matchesAJouer, uP);
    	}
     
    	public void setSelections(int selectedIndex, boolean matchesParUtilisateur, 
    			boolean matchesJoues, boolean matchesAJouer, UtilisateurParticipant uP) {
    		this.typeClassementAffiche = selectedIndex;
    		this.matchesParUtilisateur = matchesParUtilisateur;
    		this.matchesJoues = matchesJoues;
    		this.matchesAJouer = matchesAJouer;
    		this.uP = uP;
    		setModel();
    	}
     
    	public void setInfosChampionnat(InfosChampionnat infosChampionnat) {
    		this.infosChampionnat = infosChampionnat;
    	}
     
    	public void insert() {
    		MatchCase mCase = new MatchCase(infosChampionnat);
    		int idx = allDataVectors.indexOf(mCase);
     
    		if (idx != -1) {
    			MatchCase realMCase = allDataVectors.get(idx);
    			List<Match> allMatches = realMCase.getAllMatches();
     
    			if (allMatches != null) {
    				allMatches.add(sourceMatch);
     
    				if (displaying) {
    					dataVector = filterMatches(allMatches);
    					fireTableDataChanged();
    				}
    			}
    		}
    	}
     
    	public boolean isToInsert() {
    		return false;
    	}
     
    	public void setToInsert(boolean toInsert) {
    	}
     
    	public void setDisplaying(boolean displaying) {
    		this.displaying = displaying;
    	}
     
    }

  6. #6
    Membre chevronné Avatar de Claythest
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    558
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 558
    Par défaut
    Citation Envoyé par speedster
    Je ne sais pas distinguer le thread utilisateur de l'edt
    Ben en fait, tu n'es dans le thread utilisateur que dans le main, puis comme normalement tu invoques un setVisible sur une JFrame, tu passes dans l'EDT...

    Comme tous les évènements sont générés par l'EDT, si tu ne sors pas explicitement du thread courant, tout ton code s'exécutera en fait dans l'EDT... Cependant, pour des raisons de performances, il vaut mieux en sortir pour effectuer les calculs autre que ceux concernant directement l'IHM (classe SwingWorker)... et il te faut donc y "re-entrer" lorsque tu souhaites modifier des éléments de l'IHM... Bref, tu te retrouves dans un programme multi thread...

    En ce qui concerne le cache, pour savoir s'il est assez efficace ou non, il faut faire des tests... Tu peux dans un premier temps ne pas gérer de cache, laisser celui de hibernate. Si malgrès tout, tu as des temps de réponses trop lent, tu peux développer ton propre système de cache

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème rafraichissement JTable/DefaultTableModel
    Par marc.L dans le forum Composants
    Réponses: 4
    Dernier message: 20/02/2015, 09h28
  2. Sérialisation JTable DefaultTableModel
    Par superstarz dans le forum Composants
    Réponses: 4
    Dernier message: 21/01/2013, 03h09
  3. Drag n drop JTable -> JTree
    Par KeKeMaN dans le forum Composants
    Réponses: 6
    Dernier message: 14/05/2007, 15h50
  4. mis a jour Jtree depuis JTable
    Par owen2 dans le forum Composants
    Réponses: 1
    Dernier message: 12/08/2006, 14h57
  5. [Jtable] DefaultTableModel renderer des boolean
    Par lilou77 dans le forum Composants
    Réponses: 2
    Dernier message: 20/12/2005, 15h32

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo