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 :

Pattern observable - repérer des modifications d'une variable de type String


Sujet :

AWT/Swing Java

  1. #1
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2018
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Juin 2018
    Messages : 5
    Points : 3
    Points
    3
    Par défaut Pattern observable - repérer des modifications d'une variable de type String
    Bonjour à tous,

    J'en suis à ma 1ère année de java, et je cherche à développer un petit logiciel de comptabilité. Pour cela l'utilisateur rentre des catégories et des sous-catégories afin que lorsqu'il souhaite rajouter une dépense (recette, prélevement, virement) le logiciel puisse s'en servir. Je ne vous fournis pas le code car ce n'est pas intéressant ici. En revanche, j'ai supposé que l'utilisateur puisse se tromper et pour cela je me suis dit que dans l'affichage des sous-catégories, je devais permettre à l'utilisateur de pouvoir modifier ce qu'il a rentré.
    J'ai donc 2 classes, une qui s'appelle "Titre" qui extends JPanel, qui est construite avec un label et une autre qui s'appelle "TitreJtxt" qui permet d'effectuer le changement de nom de la sous-catégorie.

    voici les codes correspondants :

    Titre :

    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
     package Objet;
     
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Font;
    import java.awt.FontMetrics;
     
    import javax.swing.JLabel;
    import javax.swing.JPanel;
     
    public class Titre extends JPanel {
    	/**
             * 
             */
    	private static final long serialVersionUID = 1L;
    	protected JLabel label = new JLabel();
    	protected String str;
    	protected Font police;
     
    	public Titre() {
    	}
     
    	public Titre(String str, int size, Color color) {
    		this.setOpaque(false);
    		this.str = str;
    		police = new Font("MS sans Serif", Font.PLAIN, size);
    		this.setFont(police);
    		FontMetrics fm = getFontMetrics(police);
    		this.setPreferredSize(new Dimension(fm.stringWidth(str) + 20, 30));
    		label.setHorizontalAlignment(JLabel.LEFT);
    		label.setVerticalAlignment(JLabel.NORTH);
    		label.setText(str);
    		label.setFont(police);
    		label.setForeground(color);
    		this.add(label);
    	}
     
    	public String getStr() {
    		return str;
    	}
     
    	public void setString(String str) {
    		label.setText(str);
    	}
    }
    TitreJtxt :

    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
    package Objet;
     
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.FontMetrics;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
     
    import javax.swing.JTextField;
     
     
    public class TitreJtxt extends Titre implements MouseListener, KeyListener {
    	/**
             * 
             */
    	private static final long serialVersionUID = 1L;
    	protected JTextField JText;
     
    	public TitreJtxt() {
     
    	}
     
    	public TitreJtxt(String str, int size, Color color) {
    		super(str, size, color);
    		label.addMouseListener(this);
    		JText = new JTextField(str);
    		JText.addKeyListener(this);
    	}
     
    	public void toJTextField() {
    		this.removeAll();
    		JText.setPreferredSize(this.getSize());
    		this.add(JText);
    		revalidate();
    		repaint();
    		JText.setText(str);
    		JText.setSelectionStart(0);
    		JText.setSelectionEnd(str.length());
    		JText.requestFocus();
    	}
     
    	public void toTitre() {
    		this.removeAll();
    		FontMetrics fm = getFontMetrics(getFont());
    		try {
    			this.setPreferredSize(new Dimension(fm.stringWidth(str) + 20, 30));
    		} catch (NullPointerException e) {
     
    		}
    		label.setText(str);
    		label.notify();
    		this.add(label);
    		revalidate();
    		repaint();
    	}
     
    	@Override
    	public void mouseClicked(MouseEvent e) {
    		if (e.getClickCount() == 2)
    			toJTextField();
    	}
     
    	@Override
    	public void mouseEntered(MouseEvent e) {
     
    	}
     
    	@Override
    	public void mouseExited(MouseEvent e) {
     
    	}
     
    	@Override
    	public void mousePressed(MouseEvent e) {
     
    	}
     
    	@Override
    	public void mouseReleased(MouseEvent e) {
     
    	}
     
    	@Override
    	public void keyPressed(KeyEvent e) {
    		if (e.getKeyCode() == KeyEvent.VK_ENTER) {
    			str = JText.getText();
    			toTitre();
    		} else if (e.getKeyCode() == KeyEvent.VK_ESCAPE)
    			toTitre();
    	}
     
    	@Override
    	public void keyReleased(KeyEvent e) {
     
    	}
     
    	@Override
    	public void keyTyped(KeyEvent e) {
     
    	}
     
    	public JTextField getJText() {
    		return JText;
    	}
    }
    Maintenant, ce que je souhaite faire, c'est que lorsque je change ma variable str, dans la fonction toTitre, je "notifie" à un modelcontroller qu'il y a eu un changement et donc qu'il mette à jour la liste de sous catégories avec le nouveau nom de sous catégorie.

    Je pensais utiliser un pattern observable, mais comme j'ai déjà extends JPanel je ne peux pas, mais je ne sais pas du tout comment procéder..

    Désolé pour le pavé (un peu) long, mais il faut des explications claires.

    Je vous souhaite une bonne lecture et toute aide est la bienvenue

  2. #2
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Salut,

    Pour pouvoir traiter des modifications sur des propriétés de tes composants d'UI, tu peux utiliser javax.swing.event.SwingPropertyChangeSupport.

    Attention, dans le pattern MVC, les composants de GUI constituent la vue et ne devraient pas avoir d'attributs qui stockent des données. Ces attributs devraient être dans le modèle. Donc, cet attribut str ne devrait à priori pas être dans une classe qui étend JPanel. Pour une propriété unique, ou quelque unes, on peut éventuellement simplifier en évitant d'avoir une classe dédiée au modèle, mais le faire rend bien plus souple l'assemblage de l'UI (par exemple, parce que le modèle est partageable, ou intercheangeable indépendamment, donc sans reconstruire la GUI).

    Pour gérer les changements de propriétés selon le pattern observable, on peut utiliser la classe java.beans.PropertyChangSupport. Mais souvent, les changement de valeur de ces propriétés pouvant avoir un effet sur la vue, donc devant être fait dans le l'Event Dispatch Thread, il faudrait écouter les évenements dans un composant intermédiaire qui les renvoient vers un javax.swing.event.SwingPropertyChangeSupport, il peut être plus simple d'utiliser directement un javax.swing.event.SwingPropertyChangeSupport avec l'option notifyOnEDT. On peut doubler le SwingPropertyChangeSupport, si nécessaire, pour permettre les deux types de traitement également : dans l'EDT ou hors EDT.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  3. #3
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2018
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Juin 2018
    Messages : 5
    Points : 3
    Points
    3
    Par défaut
    Bonjour Joel, merci de votre réponse,

    J'ai regardé la javadoc de swingPropertyChangeSupport, il faudrait que finalement je passe en paramètre du constructeur SwingPropertyChangeSupport(object sourcebean) mon str qui se trouve dans Titre. Et qu'ensuite je spécifie mes écouteurs de mon str avec addPropertyChangeListener(PropertyChangeListener listener) de java.beans.swingPropertyChangeSupport

    De plus, je ne comprends pas pourquoi mon str doit se trouver à l'extérieur de mes classes. En fait j'ai conçu ces classes de façon à les rendre indépendants du programme dans lequel elles fonctionnent. mais je pense que je peux créer le swingPropertyChangeSupport à partir du programme qui les utilisent non ?

    merci

  4. #4
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par BeCoolMan Voir le message
    J'ai regardé la javadoc de swingPropertyChangeSupport, il faudrait que finalement je passe en paramètre du constructeur SwingPropertyChangeSupport(object sourcebean) mon str qui se trouve dans Titre.
    Non, la source ce n'est pas la propriété, c'est le conteneur/propriétaire de la propriété, qui correspond à la source dans l'Event. Ainsi, s'il y a plusieurs instances, tu peux savoir laquelle a émis l'événement (et donc utiliser un seul écouteur pour plusieurs sources).

    Par exemple :
    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
    public class Model {
     
    	public enum Properties {
    		TRUC;
    	}
     
    	private String truc;
     
    	private final SwingPropertyChangeSupport spcs = new SwingPropertyChangeSupport(this,true/*notify on EDT*/);
     
    	public void setTruc(String value) {
    		String old = value;
    		truc = value;
    		spcs.firePropertyChange(Properties.TRUC.name(), old, value);
    	}
     
    	public String getTruc() {
    		return truc;
    	}
     
    	public void addPropertyChangeListener(Properties property, PropertyChangeListener listener) {
    		spcs.addPropertyChangeListener(property.name(), listener);
    	}
     
    	public void removePropertyChangeListener(Properties property, PropertyChangeListener listener) {
    		spcs.removePropertyChangeListener(property.name(), listener);
    	}
     
    }

    Citation Envoyé par BeCoolMan Voir le message
    Et qu'ensuite je spécifie mes écouteurs de mon str avec addPropertyChangeListener(PropertyChangeListener listener) de java.beans.swingPropertyChangeSupport[/code]
    Pour écouter :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Model model = new Model();
    model.addPropertyChangeListener(Properties.TRUC, e-> System.out.println("La propriété " + e.getPropertyName() + " de " + e.getSource() + " a changé ! Ancienne valeur : " + e.getOldValue() + ", nouvelle valeur : " + e.getNewValue()));
    Dès que le code exécutera par exemple model.setTruc("machin"), tu verras s'affiché en console le message...

    Citation Envoyé par BeCoolMan Voir le message
    De plus, je ne comprends pas pourquoi mon str doit se trouver à l'extérieur de mes classes. En fait j'ai conçu ces classes de façon à les rendre indépendants du programme dans lequel elles fonctionnent. mais je pense que je peux créer le swingPropertyChangeSupport à partir du programme qui les utilisent non ?
    Je n'ai pas dit externe au programme, ce qui n'aurait aucun sens bien sûr. Externe à la classe composant d'UI, externe à la classe qui étend JPanel.

    Le pattern MVC met en place un trio d'objet pour construire une UI :
    1. un modèle : il contient les données et c'est tout
    2. une vue : elle affiche les données, elle présente les champs de saisie des données, et les composants d'action (boutons, menus, etc)
    3. un contrôleur qui est chargé de gérer tout ça, et en particulier la mise à jour du modèle en fonction de ce qui se passe dans la vue (si un utilisateur saisit un truc dans un champ, le contrôleur va valider (ou pas) la valeur, et décider quand la transmettre au modèle (on peut considérer que le modèle doit être mis à jour lorsqu'on clique sur un bouton "ok", ou dès qu'on sort d'un champ, ça dépend des besoins

    Ainsi, on a sépare les responsabilités de chaque partie à des classes différentes, ce qui permet de jouer avec différentes versions de plusieurs classes. Par exemple, on peut utiliser un modèle de données partagés entre plusieurs vues, ce qui fait que ce qui saisit dans l'un est visible dans l'autre. On peut aussi avoir deux vues, un pour voir et une pour éditer, qui utilise le même modèle, et un contrôleur différent, mais on duplique beaucoup moins de code (la partie modèle ne change pas). On peut utiliser le même modèle pour afficher des fiches et dans une JTable pour afficher en liste, ou afficher une fiche résumée ou une fiche avec détails, à partir du même modèle. Etc.

    Rendre indépendant la vue et le contrôleur va se traduire pas l'implémentation des interfaces d'écouteurs de composants (ActionListener par exemple) dans une classe indépendante et non sur celle qui étend JPanel.

    A noter, que dans tous les composants Swing, tu as ce trio. Enfin presque, pour les JLabel ou JPanel, il n'y en pas, parce que ce ne sont pas des composants très interactifs. Mais même dans un JButton, par exemple, tu as un modèle, une vue et un contrôleur. Dans Swing, le contrôleur est toujours interne à la vue (c'est en général assez complexe de gérer du partage de contrôle), mais il s'agit bien d'une classe séparée (ce qui permet de mutualiser éventuellement certain traitement). Dans une JTable, il y a un modèle et un contrôleur également. Le modèle est non seulement externe, mais interchangeable (on change le modèle, et la JTable n'affiche plus la même chose), ou on peut partager le modèle entre plusieurs JTable.

    A noter qu'en complément de ces notions, il y a la notion de "binding" qui permet d'associer un composant de saisi et une propriété en branchant "automatiquement" les écouteurs qui vont bien. C'est une autre façon de rendre encore plus indépendant vue et modèle.

    Un autre avantage à cette séparation et que chaque fois qu'on va par erreur rendre la vue dépendante des données, on va être bloqué : ce simple blocage peut servir d'alerte en se disant "si je n'arrive pas à le faire, c'est que ce n'est pas au bon endroit", ou "si je suis obligé de bricoler des trucs, c'est que ce n'est pas au bon endroit".

    Il y a plein d'autres avantages que tu pourras découvrir plus tard lors de certains développements et qui te feront gagner pas mal de temps (en t'évitant de modifier plein de code).
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  5. #5
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2018
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Juin 2018
    Messages : 5
    Points : 3
    Points
    3
    Par défaut
    Donc si j'ai bien compris, tout ce qu'il y a dans model doit se retrouve dans ma classe titreJtxt et dans mon majModel j'y mets model.addPropertyChangeListener(this, e);

    Par contre, pour gérer le changement (vérifier certaines propriétés du nom de la nouvelle sous-catégorie), j'utilise quelle méthode?

    Parce que le addPropertyChangeListener permet simplement d'ajouter en tant que listener mais quelle est la méthode appelée pour traiter le changement ?

    Par exemple, je change le nom de ma sous-catégorie, majModel qui observe doit recevoir le nouveau nom (avec model.add...) et doit me traiter le nouveau nom. Mais je ne vois pas où mettre le code de traitement en fait..

  6. #6
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par BeCoolMan Voir le message
    Donc si j'ai bien compris, tout ce qu'il y a dans model doit se retrouve dans ma classe titreJtxt
    Non. TitreJtxt est une vue. Ce qui doit être dans le modèle doit être dans le modèle, pas dans la vue.

    Citation Envoyé par BeCoolMan Voir le message
    et dans mon majModel j'y mets model.addPropertyChangeListener(this, e);
    C'est quoi majModel ? Ton contrôleur ? Oui, éventuellement. On devrait faire les branchements à part, à cause de l'indépendance, mais dans ton cas, si tu te limites à un contrôleur dédié à la vue et au modèle, ce sera plus simple. La vue est censé écouter le modèle pour réfléter ses changements. Mais on peut complexifier en faisant que c'est le contrôleur qui écoute le modèle et dispatche dans la vue. Ainsi, la vue ne connait pas du tout le modèle.


    Citation Envoyé par BeCoolMan Voir le message
    Par contre, pour gérer le changement (vérifier certaines propriétés du nom de la nouvelle sous-catégorie), j'utilise quelle méthode?

    Parce que le addPropertyChangeListener permet simplement d'ajouter en tant que listener mais quelle est la méthode appelée pour traiter le changement ?

    Par exemple, je change le nom de ma sous-catégorie, majModel qui observe doit recevoir le nouveau nom (avec model.add...) et doit me traiter le nouveau nom. Mais je ne vois pas où mettre le code de traitement en fait..
    Le traitement, c'est dans l'écouteur justement.

    Je n'ai pas le temps de te faire un exemple concret complet pour l'instant. Je verrais plus tard. D'autant plus qu'il y a des trucs à revoir dans ton code où tu te compliques bien la vie (gestion de KeyListener et MouseListener, alors qu'il vaut mieux utiliser des gestionnaires moins bas niveau, la gestion de la taille préférentielle superflue à priori (pourquoi faire, surtout que çà va déconner avec une police de taille 48 par exemple), pourquoi retirer les composants pour les remettre, etc ?)
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  7. #7
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2018
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Juin 2018
    Messages : 5
    Points : 3
    Points
    3
    Par défaut
    D'accord, il n'y a pas de soucis, je vais digérer toutes les informations que vous m'avez donné et je vais les appliquer,

    Merci pour vôtre aide en tout cas

Discussions similaires

  1. Suppression des doublons dans une variable de type tableau
    Par damsmut dans le forum Général VBA
    Réponses: 2
    Dernier message: 23/07/2019, 10h36
  2. Réponses: 6
    Dernier message: 14/02/2007, 21h08
  3. Des " dans une variable de type String
    Par 4lkaline dans le forum Langage
    Réponses: 6
    Dernier message: 06/11/2006, 14h20
  4. convertir une variable de type String en Number
    Par lilbrother974 dans le forum Flash
    Réponses: 13
    Dernier message: 06/09/2006, 08h28
  5. Ajouter a une variable de type string, un entier
    Par Little-Freud dans le forum SL & STL
    Réponses: 12
    Dernier message: 05/03/2005, 19h33

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