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

AWT/Swing Java Discussion :

[Swing] Engorgement de l'interface graphique à cause de rafraichissements massifs


Sujet :

AWT/Swing Java

  1. #1
    Membre confirmé
    Inscrit en
    Mars 2005
    Messages
    60
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 60
    Par défaut [Swing] Engorgement de l'interface graphique à cause de rafraichissements massifs
    Bonjour,

    J'utilise dans mon interface graphique une JTable représentant des objets "métier" en mémoire (une ligne par objet et une colonne par attribut de l'objet) qui sont massivement mis à jour lors du cycle de vie de l'application.
    Pour répercuter les changements d'états de ces objets métier dans l'interface graphique, je déclenche un PropertyChangeListener à la modification de chaque attribut de mon objet "métier" dans son setXXX correspondant et j'implémente un PropertyChangeListener dans le TableModel de manière à ce qu'il mette à jour sa vue (JTable) à chaque fois qu'il reçoit un PropertyChangeEvent (à chaque setXXX de chaque objet en mémoire alors).
    De ce fait, je constate que l'interface graphique est complètement saturée par le débit d'évènements générés et qu'elle a à traiter.
    N'auriez vous pas une autre stratégie un peu plus optimale pour garantir une mise à jour fluide du modèle dans la vue?
    Merci d'avance pour vos réponses.

  2. #2
    Membre Expert
    Avatar de CheryBen
    Inscrit en
    Mai 2005
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Âge : 43

    Informations forums :
    Inscription : Mai 2005
    Messages : 1 599
    Par défaut
    Bonjour, est-ce que tu fais bien toutes les mises à jour de l'interface à partir de l'EDT? Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    public void propertyChanged(PropertyChangeEvent evt) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                // MAJ
            }
        });
    }

  3. #3
    Membre confirmé
    Inscrit en
    Mars 2005
    Messages
    60
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 60
    Par défaut
    Merci pour ta réponse rapide.
    Oui je fais bien gaffe à ce qu'il soit exécuté dans l'EDT, mais rien n'y fait...
    Je crois que le volume des events générés doit vraiment être monstrueux...

  4. #4
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par yelbied Voir le message
    et j'implémente un PropertyChangeListener dans le TableModel de manière à ce qu'il mette à jour sa vue (JTable) à chaque fois qu'il reçoit un PropertyChangeEvent (à chaque setXXX de chaque objet en mémoire alors).
    On pourrait également voir le code de ta méthode propertyChange() ?

    a++

  5. #5
    Expert confirmé
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Par défaut
    Bonjour

    Et au niveau de ton modèle que déclenches tu comme méthode pour demander la mise à jour de la JTable?

  6. #6
    Membre confirmé
    Inscrit en
    Mars 2005
    Messages
    60
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 60
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Salut,


    On pourrait également voir le code de ta méthode propertyChange() ?

    a++
    J'ai simplifié à fond la description de mon problème.
    En réalité, j'utilise un JTreeTable (http://java.sun.com/products/jfc/tsc...reloading_data) qui est, comme son nom l'indique, un composant hybride entre une JTree et une JTable qui permet d'afficher à la fois de manière arborescente et matricielle un modèle de données.
    Mes objets "métier" sont accessibles dans le modèle de la JTree, qui lui implémente un PropertyChangeListener pour écouter les changements :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    public class TreeTableModel implements TreeModel, PropertyChangeListener {
    (...)
    public void propertyChange(final PropertyChangeEvent e) {
        fireTreeNodesChanged(e.getSource(), new Object[] { e.getSource() }, null, null);
        }
    (...)
    }
    La classe TreeTableModel relaie le PropertyChangeEvent en créant un TreeModelEvent vers le modèle de la JTable à proprement dit qui implémente un TreeModelListener pour écouter ces évènements :
    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
     
    public class TreeTableModelAdapter extends AbstractTableModel {
    (...)
        private TreeTableModel treeModel;
    (...)
        treeTableModel.addTreeModelListener(new TreeModelAdapter() {
          public void treeNodesChanged(TreeModelEvent e) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                   fireTableDataChanged();
                }
            });
          }
        }
    (...)
    }
    De ce fait le TreeModelEvent sert de passerelle entre le modèle de la JTree et le modèle de JTable pour propager l'information d'update de la vue.
    Après, le fireTableDataChanged() demande à la JTable de se mettre à jour à partir de son modèle
    C'est un peu complexe tout ça, donc si vous avez besoin d'éclaircissements, n'hésitez pas.

  7. #7
    Membre Expert Avatar de Uther
    Homme Profil pro
    Tourneur Fraiseur
    Inscrit en
    Avril 2002
    Messages
    4 702
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Tourneur Fraiseur

    Informations forums :
    Inscription : Avril 2002
    Messages : 4 702
    Par défaut
    Une solution que je vois c'est de te débrouiller via un timer pour que la mise a jour ne soie effectuée que une fois toutes les secondes au maximum.

    Au lieu de lancer le rafraichissement tu met une variable à true.
    tu lances un timer en daemon qui toutes les seconde fait la mise à jour si la variable vaut true,et la remet à false.

  8. #8
    Expert confirmé
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Par défaut
    Effectivement c'est un poil violent, tu demandes le rechargement de toute la table rien que pour une pauvre valeur changée...

    Le point serait de pouvoir cibler quelle est la ligne de la JTable est modifiée (ou quelles sont les lignes) et de ne faire qu'un fireTableRowsUpdated qui est carrément moins violent qu'un fireTableDataChanged

  9. #9
    Membre confirmé
    Inscrit en
    Mars 2005
    Messages
    60
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 60
    Par défaut
    Citation Envoyé par Uther Voir le message
    Une solution que je vois c'est de te débrouiller via un timer pour que la mise a jour ne soie effectuée que une fois toutes les secondes au maximum.

    Au lieu de lancer le rafraichissement tu met une variable à true.
    tu lances un timer en daemon qui toutes les seconde fait la mise à jour si la variable vaut true,et la remet à false.
    J'ai essayé cette solution, et même avec un timer à une micro seconde, le GUI ne se met plus à jour "au fil de l'eau" et les valeurs de mes objets métiers restent figées dessus alors qu'elles ont bien changé en réalité (il faut donner le focus "à la main" avec le clavier ou la souris à une cellule pour qu'elle soit effectivement redessinée avec la value mise à jour...).

  10. #10
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Ton problème vient surement du fireTableDataChanged() Cela indique que toutes les données du modèle ont été modifié, et cela implique un rechargement complet de la table... ce qui doit sûrement être assez lourd si tu le répête à chaque petite modif...

    Il serait préférable de récupérer l'objet qui a été modifié via e.getSource() et de rechercher son index dans ton modèle afin de lancer un fireTableRowsUpdated(index,index), ce qui indiquera seulement la mise à jour d'une ligne ce qui serait surement bien moins lourd.

    Mieux si tu arrives à déterminer la colonne qui a été modifié, tu pourrais lancer un fireTableCellUpdated(). Bref il est préférable de lancer l'évènement le plus précis sur la modif

    Je n'ai jamais utilisé de JTreeTable, mais tout ceci est vrai pour une simple JTable, donc cela doit l'être également dans ce cas


    a++

    [edit] Légèrement grillé

  11. #11
    Membre confirmé
    Inscrit en
    Mars 2005
    Messages
    60
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 60
    Par défaut
    Citation Envoyé par sinok Voir le message
    Effectivement c'est un poil violent, tu demandes le rechargement de toute la table rien que pour une pauvre valeur changée...

    Le point serait de pouvoir cibler quelle est la ligne de la JTable est modifiée (ou quelles sont les lignes) et de ne faire qu'un fireTableRowsUpdated qui est carrément moins violent qu'un fireTableDataChanged
    Oui je sais, mais c'est un poil difficile de transmettre les coordonnées d'une cellule dans un TreeModelEvent
    Et puis l'information remonte à l'origine de mon objet métier qui lui ne sait pas sur quelle ligne il est affiché sur la JTable...

  12. #12
    Membre confirmé
    Inscrit en
    Mars 2005
    Messages
    60
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 60
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Ton problème vient surement du fireTableDataChanged() Cela indique que toutes les données du modèle ont été modifié, et cela implique un rechargement complet de la table... ce qui doit sûrement être assez lourd si tu le répête à chaque petite modif...

    Il serait préférable de récupérer l'objet qui a été modifié via e.getSource() et de rechercher son index dans ton modèle afin de lancer un fireTableRowsUpdated(index,index), ce qui indiquera seulement la mise à jour d'une ligne ce qui serait surement bien moins lourd.

    Mieux si tu arrives à déterminer la colonne qui a été modifié, tu pourrais lancer un fireTableCellUpdated(). Bref il est préférable de lancer l'évènement le plus précis sur la modif

    Je n'ai jamais utilisé de JTreeTable, mais tout ceci est vrai pour une simple JTable, donc cela doit l'être également dans ce cas


    a++

    [edit] Légèrement grillé
    En effet, le problème vient de la demande de mise de TOUT le tableau ; j'ai essayé avec fireTableRowsUpdated, et ça va un peu mieux.
    Je vais chercher un moyen de trouver les coordonnées de la cellule exacte à modifier, et je vous tiens au courant.
    Par contre, j'ai remarqué que quand j'utilise le fireTableRowsUpdated, ça me cassait tout l'affichage de mon tableau (utilise les rendrers par défaut au lieu que ceux que j'avais définis), quelqu'un aurait une idée sur ce point ?

  13. #13
    Membre confirmé
    Inscrit en
    Mars 2005
    Messages
    60
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 60
    Par défaut
    Citation Envoyé par yelbied Voir le message
    Par contre, j'ai remarqué que quand j'utilise le fireTableRowsUpdated, ça me cassait tout l'affichage de mon tableau (utilise les rendrers par défaut au lieu que ceux que j'avais définis), quelqu'un aurait une idée sur ce point ?
    Un autre problème gênant que j'ai remarqué en procédant ainsi : je n'arrive plus à sélectionner une ligne de mon tableau (la sélection bleue par la souris ne fonctionne plus).

Discussions similaires

  1. interface graphique swing
    Par franfr57 dans le forum AWT/Swing
    Réponses: 7
    Dernier message: 14/11/2006, 02h05
  2. [DEBUTANT][GROS NEWBIE][SWING] Interface graphique
    Par GyZmoO dans le forum AWT/Swing
    Réponses: 8
    Dernier message: 21/05/2006, 00h13
  3. [Swing] Bug interface graphique
    Par thegreatbato dans le forum AWT/Swing
    Réponses: 5
    Dernier message: 15/05/2006, 11h51
  4. [Swing] Création d'une interface graphique SWING + MVC
    Par Sylmandel dans le forum AWT/Swing
    Réponses: 2
    Dernier message: 21/04/2006, 09h03
  5. [package][swing] Interface graphique
    Par _KB_ dans le forum AWT/Swing
    Réponses: 9
    Dernier message: 06/04/2006, 19h38

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