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 :

Problème Optimisation ListCellRenderer


Sujet :

Composants Java

  1. #1
    Membre du Club
    Homme Profil pro
    Développeur Java
    Inscrit en
    Septembre 2006
    Messages
    81
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Septembre 2006
    Messages : 81
    Points : 51
    Points
    51
    Par défaut Problème Optimisation ListCellRenderer
    Bonjour à tous!

    Pour une application de caisse avec une prévisualisation du ticket, j'ai un problème de lenteur avec ma Jlist et mon ListCellRenderer.

    En résumé, il s'agit d'un panel qui contient un JScrollPane qui contient une Jlist. Les élements de la liste sont customisés par le ListCellRenderer.

    Lors de l'ajout des premiers élements, l'opération s'éxecute rapidement mais dès que je dépasse la taille de ma JScrollPane , il y a de gros ralentissements à chaque ajout d'élement.

    En lisant certains forums, ils parlent qu'il ne faut pas trop charger la méthode getListCellRendererComponent(), dans mon cas je ne pense pas que les différents tests prennent énormement de temps.


    Création de la Jlist avec le ScrollPane :

    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
    		//ticket et boutons défilement dans panel du bas
    		list = new JList(getTicket());
            list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
            list.setSelectedIndex(1);
            list.setCellRenderer(new TicketListRenderer());
            list.setFont(new Font("Helvetica", Font.PLAIN, 11));
     
            //ici on perd la synchronisation avec l'EDT si le premier article saisi vient d'un scan... 
            //alors j'ajoute le mouselistener par SwingUtilities pour etre sur que cet event soit toujours synchro
            SwingUtilities.invokeLater(new Runnable() {
    			public void run() {
    		        list.addMouseListener(new MouseListener() {
    					public void mouseReleased(MouseEvent arg0) {
    						...
    					}
     
    					public void mousePressed(MouseEvent arg0) {}
    					public void mouseExited(MouseEvent arg0) {}
    					public void mouseEntered(MouseEvent arg0) {}
    					public void mouseClicked(MouseEvent arg0) {}
    				});
    			}
            });
     
            listScrollPane = new JScrollPane(list);
            listScrollPane.setPreferredSize(new Dimension(lliste, hliste));
            listScrollPane.setBorder(BorderFactory.createLineBorder(Color.black, 2));
            listScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
            listScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
            listScrollPane.setViewportView(list);
    Voici la classe qui contient le Renderer :

    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
    public class TicketListRenderer extends DefaultListCellRenderer {
    	String separateur = "_________________________________________________________________________";
    	DAOMagasin mag = Global.magasin;
     
    	private static final long serialVersionUID = 1L;
     
    	public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
    		JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
     
    		label.setOpaque(true);
     
    		if(index % 2 == 1){
    			label.setBackground(new Color(240,240,240));
    		}
     
    		label.setBorder(null);
     
    		if(isSelected){
    			label.setBackground(new Color(215,228,189));
    		}
     
    		if(index == 0){
    			if(mag.getMagasinId() > 0){
    				label.setIcon(new ImageIcon(Global.ini.getPath_Images() + "logo_jumbo_ticket.JPG"));
     
    				String m2 = mag.getAdresse2();
     
    				if(m2 == null || "".equals(m2)){
    					m2 = "";
    				}else{
    					m2 = ", " + m2;
    				}
     
    				int lang = OperateurController.getOperateurCourant().getLangueId();
    				String tel = Util.getTrad(Global.mapTrad, "ticket.tel", lang);
     
    				String info = "<html><center>" + mag.getNom() + ",  " + mag.getNpa() + "<br>" +
    					mag.getAdresse1() + m2 + "<br>" +
    					tel + mag.getTelephone() + "<br>" + 
    					"<b>" + mag.getUrl() + "<b>" + "<br>" +
    					separateur + "<br>" +
    					"</html>";
     
    				label.setText(info);
    				label.setVerticalTextPosition(JLabel.BOTTOM);
    				label.setHorizontalTextPosition(JLabel.CENTER);
    				label.setFont(new Font("Helvetica", Font.PLAIN, 10));
    				label.setHorizontalAlignment(SwingConstants.CENTER);
    				label.setOpaque(false);
    				label.setBorder(null);
    				label.setPreferredSize(new Dimension(444, 145));
    			}
    		}
    		else{
    			String val = (String)value;
     
    			setForeground(Color.black);
     
    			if(index == list.getModel().getSize()-1){
    				setForeground(Color.blue);
    			}
     
    			int nbt = Util.compteNombreCar((String)value, "<tr>") - 1;
    			label.setPreferredSize(new Dimension(444, 20 * nbt));
     
    			if(val.contains("TXTAJOUT:" + ConstantesTRA.EXTOURNE_ARTICLE)){
    				label.setForeground(Color.red);
    			}
    			if(val.contains("RETOUR:")){
    				label.setForeground(new Color(11, 156, 28));
    			}
    			else if(val.contains("DEMANDEMONNAIE")){
    				label.setForeground(Color.black);
    			}
    			else if(val.contains(":RABMYONE") || val.contains("RABAIS_CLIENT") 
    					|| val.contains("BON:") || val.contains("RABAISBT:11")
    					|| val.contains("RABAIS:")
    			){
    				label.setOpaque(false);
    				label.setBorder(null);
    			}
    			else if(val.contains("TRANSITION")){
    				if(val.equals("TRANSITIONPAIEMENT")){
    					String info = "<html><center>" + separateur + "<br>" + "</html>";
    					label.setText(info);
    					label.setVerticalTextPosition(JLabel.BOTTOM);
    					label.setHorizontalTextPosition(JLabel.CENTER);
    					label.setFont(new Font("Helvetica", Font.PLAIN, 10));
    					label.setHorizontalAlignment(SwingConstants.CENTER);
    					label.setPreferredSize(new Dimension(444, 11));
    				}
     
    				label.setOpaque(false);
    				label.setBorder(null);
    				label.setForeground(Color.black);
    			}
    			else if(val.contains("MOYENPAIEMENT")){
    				label.setOpaque(false);
    				label.setBorder(null);
    				label.setForeground(Color.black);
    			}
    		}
     
    		return this;
    	}
    }
    Et une partie du ticket, à noter qu'on utilise souvent SwingUtilities.invokeLater car notre caisse contient des scanners qui nous font perdre la synchronisation avec l'EDT :

    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 Ticket extends DefaultListModel<Object> implements ListDataListener {
    		public Ticket(CaisseController contr){
    		super();
    		addListDataListener(this);
     
    		SwingUtilities.invokeLater(new Runnable() {
    			public void run() {
    				//l'élément vide affichera le logo au début du ticket
    				addElement("");
    			}
    		});
    		ensureCapacity(1000);
    		this.contr = contr;
    		this.lang = contr.getOperateurCourant().getLangueId();
    	}
    public void affiche(DAOTransaction t){
    	String aff = "<html><body><table BORDER=\"" + border + "\" width=\"100%\"><tr>";
     
    	...
    	aff += "</html>";
     
    	final String affi = aff;
     
    	SwingUtilities.invokeLater(new Runnable() {
    		public void run() {
    			addElement(affi);
    		}
    	});
    }

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

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Points : 12 977
    Points
    12 977
    Par défaut
    On dira qu'appeler un DAO, et donc un service DB dans un Renderer n'est pas franchement la plus brillante des idées.

    Le renderer devrait avoir à disposition toutes les données de façon immédiate avant de commencer le rendu.
    Imagine le nombre d'appels nécessaires sinon, sans même parler du fait que le renderer est appelé à chaque repaint du composant pour les items visibles.

    Il vaudrait mieux que ces données soient dans le modèle de ta JList.
    Hey, this is mine. That's mine. All this is mine. I'm claiming all this as mine. Except that bit. I don't want that bit. But all the rest of this is mine. Hey, this has been a really good day. I've eaten five times, I've slept six times, and I've made a lot of things mine. Tomorrow, I'm gonna see if I can't have sex with something.

  3. #3
    Membre du Club
    Homme Profil pro
    Développeur Java
    Inscrit en
    Septembre 2006
    Messages
    81
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Septembre 2006
    Messages : 81
    Points : 51
    Points
    51
    Par défaut
    Effectivement nous utilisons un DAO mais cet objet vient de notre classe Global qui stocke en cache des informations, ce DAO est populé depuis une autre classe.

    On peut dire ici que le renderer a les données à disposition

  4. #4
    Membre du Club
    Homme Profil pro
    Développeur Java
    Inscrit en
    Septembre 2006
    Messages
    81
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Septembre 2006
    Messages : 81
    Points : 51
    Points
    51
    Par défaut
    Bon, j'ai peut etre un début de piste. J'ajouté des traces de temps dans le code de mon ticket :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    long l1 = System.currentTimeMillis();
    			//c'est quoi la différence entre addElement() et add()??
    			//addElement(affi);
    			add(getSize(), affi);
    			System.out.println("t : " + (System.currentTimeMillis() - l1));
    qui me donnent des résultats étranges :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    t : 26
    t : 37
    t : 54
    t : 53
    t : 231
    t : 240
    t : 277
    t : 55
    t : 412
    t : 906
    comment est-ce que je pourrais optimiser ces ajouts? J'ai trouvé ca sur google http://dhasa.blogspot.ch/2007/11/jav...rformance.html , qui a l'air de refleter mon problème mais je n'arrive pas à implémenter ca correctement pour que ca fonctionne comme voulu!

  5. #5
    Membre du Club
    Homme Profil pro
    Développeur Java
    Inscrit en
    Septembre 2006
    Messages
    81
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Septembre 2006
    Messages : 81
    Points : 51
    Points
    51
    Par défaut
    Bon hé bien la raison du ralentissement est du au code html utilisé, il semble trop lourd.

    Maintenant je dois aborder la situation différemment :

    Dans ma JList, je dois afficher des éléments de la manière d'un tableau, mais en plus sur 2 lignes par ligne du tableau...

    La première idée serait d'utiliser String.format pour avoir un alignement correct :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    String.format("%-5.5s %-56s %13s %13s %18s", t1, t2, t3, t4, t5);
    Ceci m'aligne mes lignes correctement. Sauf que maintenant je dois ajouter une deuxième ligne à ma ligne de la JList (une deuxième ligne au JLabel en fait).

    Alors je me retrouve face au problème suivant :
    1. comment faire 2 lignes dans un JLabel -> en utilisant du code html vous me direz!
    1.1 oui mais si je mets du html, mes espaces générés par String.format disparaissent car html les vire!
    1.2 si je fais un replace de mes " " par des "&nbsp;", ca me donne une largeur différente de celle définie au départ!

    Je suis dans tous les cas coincé!

    Quelqu'un aurai une idée à proposer? J'en peux plus là!

    Merci d'avance

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

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Points : 12 977
    Points
    12 977
    Par défaut
    Un JPanel en vertical box contenant deux labels?

    Ou si tu veux un réel contrôle sur la disposition, un JComponent custom dessinant tout au pixel près via uen redéfinition de paintComponent et l'emploi d'une police monospaced (police dont la taille est la même en permanence, permettant de déterminer directement quelle sera la taille du texte.)
    Hey, this is mine. That's mine. All this is mine. I'm claiming all this as mine. Except that bit. I don't want that bit. But all the rest of this is mine. Hey, this has been a really good day. I've eaten five times, I've slept six times, and I've made a lot of things mine. Tomorrow, I'm gonna see if I can't have sex with something.

  7. #7
    Membre du Club
    Homme Profil pro
    Développeur Java
    Inscrit en
    Septembre 2006
    Messages
    81
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Septembre 2006
    Messages : 81
    Points : 51
    Points
    51
    Par défaut
    Dans mon renderer?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    	public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
    		JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
    J'ai déjà essayé de lui ajouter un JPanel avec 2 labels mais rien ne s'affichait. Le soucis j'ai l'impression c'est que comme le label contient le texte tout autre composant se comporte mal.

    Et après j'ai peur pour les performances de mon renderer si je lui ajoute un panel et 2 labels

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

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Points : 12 977
    Points
    12 977
    Par défaut
    Ce sera largement moins pire que du HTML.
    Hey, this is mine. That's mine. All this is mine. I'm claiming all this as mine. Except that bit. I don't want that bit. But all the rest of this is mine. Hey, this has been a really good day. I've eaten five times, I've slept six times, and I've made a lot of things mine. Tomorrow, I'm gonna see if I can't have sex with something.

  9. #9
    Membre du Club
    Homme Profil pro
    Développeur Java
    Inscrit en
    Septembre 2006
    Messages
    81
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Septembre 2006
    Messages : 81
    Points : 51
    Points
    51
    Par défaut
    Ok j'essaierai lundi mais sans grande conviction

    Sinok tu as déjà fait ça? J'aimerai être sur que ça fonctionne avant de le faire

  10. #10
    Membre du Club
    Homme Profil pro
    Développeur Java
    Inscrit en
    Septembre 2006
    Messages
    81
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Septembre 2006
    Messages : 81
    Points : 51
    Points
    51
    Par défaut
    Bonjour!

    Voilà j'ai essayé mais comme je m'y attendais, ca ne fonctionne pas!

    Voici la classe de mon rendu
    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
    public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
    		JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
     
    		//label.setOpaque(true);
     
    		//if(index % 2 == 1){
    			label.setBackground(new Color(240,240,240));
    		//}
     
    		label.setText("");
    		label.setPreferredSize(new Dimension(100, 60));
     
    		JComponent p = new JPanel();
    		p.setOpaque(true);
    		p.setPreferredSize(new Dimension(90, 55));
    		p.setBorder(BorderFactory.createLineBorder(Color.pink));
    		p.setLayout(new BoxLayout(p, BoxLayout.PAGE_AXIS));
     
    		label.add(p);
     
    		JLabel l1 = new JLabel("1");
    		l1.setOpaque(true);
    		l1.setPreferredSize(new Dimension(85, 25));
    		l1.setBorder(BorderFactory.createLineBorder(Color.green));
    		p.add(l1);
     
    		JLabel l2 = new JLabel("2");
    		l2.setPreferredSize(new Dimension(85, 25));
    		l2.setBorder(BorderFactory.createLineBorder(Color.green));
    		p.add(l2);
     
    		return this;
    	}
    mais dans me fenetre, seul les premiers labels s'affichent (sans contenu vu que je l'ai enlevé). Aucun des composants interne ne fait quoi que ce soit, aucun border d'affiché... rien

    Un petit coup de main serait pas de refus s'il vous plait

  11. #11
    Membre du Club
    Homme Profil pro
    Développeur Java
    Inscrit en
    Septembre 2006
    Messages
    81
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Septembre 2006
    Messages : 81
    Points : 51
    Points
    51
    Par défaut
    fonctionne mieux!

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

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Points : 12 977
    Points
    12 977
    Par défaut
    Logique.
    Et niveau performances, ça a résolu le problème?
    Hey, this is mine. That's mine. All this is mine. I'm claiming all this as mine. Except that bit. I don't want that bit. But all the rest of this is mine. Hey, this has been a really good day. I've eaten five times, I've slept six times, and I've made a lot of things mine. Tomorrow, I'm gonna see if I can't have sex with something.

  13. #13
    Membre du Club
    Homme Profil pro
    Développeur Java
    Inscrit en
    Septembre 2006
    Messages
    81
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Septembre 2006
    Messages : 81
    Points : 51
    Points
    51
    Par défaut
    Citation Envoyé par sinok Voir le message
    Logique.
    Pas faux

    Citation Envoyé par sinok Voir le message
    Et niveau performances, ça a résolu le problème?
    Les performances sont excellentes, si j'avais su je serais jamais parti sur du html mais bon... Enfin maintenant après moult travail tout fonctionne à merveille! Merci du tuyau Sinok

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

Discussions similaires

  1. Problème Optimisation JSON Parser
    Par eento dans le forum Android
    Réponses: 18
    Dernier message: 12/07/2012, 16h58
  2. [MySQL] Probléme optimisation création croisé dynamique
    Par kamnouz dans le forum PHP & Base de données
    Réponses: 18
    Dernier message: 18/11/2011, 15h40
  3. [problème optimisation] Colorier lignes
    Par iMaTh dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 05/09/2011, 10h05
  4. Problème optimisation requête
    Par ludo00002 dans le forum SQL
    Réponses: 2
    Dernier message: 29/09/2009, 16h02
  5. problème optimisation sql dans RPG ILE
    Par Pierre Quefer dans le forum AS/400
    Réponses: 4
    Dernier message: 19/02/2009, 13h09

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