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

Java Discussion :

Optimisation d'une fonction de découpage en sous-chaine


Sujet :

Java

  1. #1
    Membre actif
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    433
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 433
    Points : 240
    Points
    240
    Par défaut Optimisation d'une fonction de découpage en sous-chaine
    Bonjour,

    J'ai hésité à mettre ce sujet dans java général, interfaces graphiques ou algorithmique, mais je pense qu'il a plus sa place ici.

    La fonction drawString(String texte, int posX, int posY) permet d'écrire une ligne de texte dans un panel. J'ai voulu écrire une fonction (plutot une méthode statique) qui permet d'écrire un paragraphe complet. Cette fonction doit reconnaitre les saut de ligne "\n" pour faire des retours à la ligne, et le dernier argument permet de définir une taille maximum (en pixel) pour le paragraphe. Si une ligne dépasse cette taille, il va falloir couper la ligne en ajoutant artificiellement des retours à la ligne.

    La fonction que j'ai écrit marche, mais semble être une usine à gaz !
    Je voudrais votre avis, et si possible l'optimiser. Voila le code:

    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
    public static void dessinerParagraphe(Graphics g, String paragraphe, int posX, int posY, int longMax) {
     
    	int i;
    	FontMetrics fm = g.getFontMetrics();
     
    	// Le vecteur suivant doit contenir toutes les lignes écrite à la fin
    	Vector<String> ligne = new Vector<String>();
     
     
    	// On coupe le paragraphe en section
    	String section[] = paragraphe.split("\n");
    	int nbSection = section.length;
     
    	for(i=0; i < nbSection; i++) {
     
    		// On teste si la ligne est plus longue que la taille spécifiée
    		if(longMax > 0 && fm.stringWidth(section[i]) > longMax) {
     
    			int mem = 0, k = 0;
    			String ssChaine;
    			StringBuffer sb = new StringBuffer(section[i]);
     
    			do {
    				// On garde en mémoire le premier espace
    				mem = k;
     
    				// On cherche le suivant espace
    				k = sb.indexOf(" ", mem+1);
     
    				// Si on n'est pas arrivé en bout de chaine
    				if( k != -1) {
     
    					// On prends la dernière sous chaine
    					ssChaine = sb.substring(0, k);
     
    					// Si on dépasse la taille max, alors...
    					if( fm.stringWidth(ssChaine) > longMax ) {
     
    						// On ajoute la sous chaine précédente
    						ssChaine = sb.substring(0, mem);
    						ligne.add(ssChaine);
     
    						// On la retire du buffer
    						sb.delete(0,mem+1);
    					}
    				}
     
    			} while( k != -1 );
     
    			// On ajoute le dernier bout de chaine
    			ssChaine = sb.toString();
    			ligne.add(ssChaine);
     
    		} else {
    			// Si pas de restriction sur la longueur, on n'a
    			// plus qu'a ajouter la ligne sans découper !
    			ligne.add(section[i]);
    		}
    	}
     
     
    	// On récupère la hauteur d'une ligne
    	int hautLigne = fm.getHeight();
     
    	// On dessine ligne par ligne
    	int nbLigne = ligne.size();
     
    	for(i=0; i < nbLigne; i++) {
    		g.drawString( ligne.get(i) , posX, posY);
    		posY += hautLigne;
    	}
    }
    Merci aux courageux qui auront pris le temps de lire le code !

  2. #2
    Membre expert
    Avatar de natha
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    2 346
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2006
    Messages : 2 346
    Points : 3 083
    Points
    3 083
    Par défaut
    Ton code n'est pas correct. Il faut utiliser des classes de l'API un peu plus complexes.

    Voici une méthode à moi pour faire un drawString évolué :

    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
    	/**
             * Draw some text in given rectangle shape.
             *
             * @param g2D The {@link Graphics2D} to draw on.
             * @param rect The text area.
             * @param font The font to be used.
             * @param texts Array of lines to be drawn.
             */
    	public static void drawText(Graphics2D g2D, Rectangle2D rect, Font font, String... texts) {
    		// Shape not valid => return immediately
    		if (rect.getWidth() <= 0 || rect.getHeight() <= 0) {
    			return;
    		}
     
    		// Clip area and translate coordinates
    		Shape lastClip = g2D.getClip();
    		Area newClip = new Area(lastClip);
    		newClip.intersect(new Area(rect));
    		g2D.setClip(newClip);
    		double x = rect.getX();
    		double y = rect.getY();
    		g2D.translate(x, y);
     
    		// Init vars
    		float breakWidth = (float) rect.getWidth();
    		float drawPosY = 0;
    		FontRenderContext frc = g2D.getFontRenderContext();
     
    		for (String text : texts) {
    			// Create attributed string and iterator
    			AttributedString ressource = new AttributedString(text, font.getAttributes());
    			AttributedCharacterIterator paragraph = ressource.getIterator();
    			int paragraphStart = paragraph.getBeginIndex();
    			int paragraphEnd = paragraph.getEndIndex();
    			LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(paragraph, frc);
     
    			// Set position to the index of the first character in the paragraph.
    			lineMeasurer.setPosition(paragraphStart);
     
    			// Get lines until the entire paragraph has been displayed.
    			while (lineMeasurer.getPosition() < paragraphEnd && drawPosY + g2D.getFontMetrics(font).getAscent() < rect.getHeight()) {
    				// Retrieve next layout. A cleverer program would also cache
    				// these layouts until the component is re-sized.
    				TextLayout layout = lineMeasurer.nextLayout(breakWidth);
     
    				// Compute pen x position. If the paragraph is right-to-left we
    				// will align the TextLayouts to the right edge of the panel.
    				// Note: this won't occur for the English text in this sample.
    				// Note: drawPosX is always where the LEFT of the text is placed.
    				float drawPosX = layout.isLeftToRight() ? 0 : breakWidth - layout.getAdvance();
     
    				// Move y-coordinate by the ascent of the layout.
    				drawPosY += layout.getAscent();
     
    				// Draw the TextLayout at (drawPosX, drawPosY).
    				layout.draw(g2D, drawPosX, drawPosY);
     
    				// Move y-coordinate in preparation for next layout.
    				drawPosY += layout.getDescent() + layout.getLeading();
    			}
    		}
     
    		// Restore position and clip area
    		g2D.translate(-x, -y);
    		g2D.setClip(lastClip);
    	}
    Je crois que les commentaires sont assez explicites pour peu que tu comprennes l'anglais.
    En gros j'écris des lignes (pas de prise en compte du séparateur de ligne mais je fournis un tableau de lignes à la méthode, suffit d'adapter) dans un rectangle. Ca comprend la largeur du rectangle (ce que toi tu cherches) et en plus je gère la hauteur pour éviter d'essayer d'écrire du texte dans un endroit où de toute façon il ne sera pas affichable.
    Il faut bien sûr fournir le Graphics2D sur lequel on dessine.

  3. #3
    Membre actif
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    433
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 433
    Points : 240
    Points
    240
    Par défaut
    Oula, j'ai l'impression que ce code est un peu plus complexe ^^
    Ca vient du fait que je ne connais pas les classes aussi.
    Je l'utiliserai si jamais la mienne ne me donne pas de résultat satisfesants.

    Merci !

  4. #4
    Membre expert
    Avatar de natha
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    2 346
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2006
    Messages : 2 346
    Points : 3 083
    Points
    3 083
    Par défaut
    J'ai l'impression que ton code ne fonctionnera pas correctement lorsqu'il s'agira de couper les mots.
    L'avantage de ma méthode est que si le mot sort de la zone, il passe à la ligne, et s'il est trop long pour seul tenir sur une ligne, il sera coupé. C'est tout Java qui gère.

    Il y aura des cas de figures dans lesquels ta méthode ne donnera pas le résultat attendu (mots plus longs qu'attendu ou largeur autorisée trop petite).

  5. #5
    Membre actif
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    433
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 433
    Points : 240
    Points
    240
    Par défaut
    En effet, je recherche des espaces pour couper les lignes, et j'ai pensé à ce cas de figure. Si un mot est plus long que la longueur max, je ne sais même pas comment va réagir ma méthode, l'effet sera indésiré.

  6. #6
    Membre expert
    Avatar de natha
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    2 346
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2006
    Messages : 2 346
    Points : 3 083
    Points
    3 083
    Par défaut
    Citation Envoyé par FabaCoeur Voir le message
    En effet, je recherche des espaces pour couper les lignes, et j'ai pensé à ce cas de figure. Si un mot est plus long que la longueur max, je ne sais même pas comment va réagir ma méthode, l'effet sera indésiré.
    La mienne gère ça donc je pense que c'est mieux pour toi d'essayer de comprendre mon code et l'adapter à ton besoin même si ça te prendra un peu plus de temps.
    Voili voili.

  7. #7
    Membre actif
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    433
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 433
    Points : 240
    Points
    240
    Par défaut
    En fait je partais du principe que l'utilisateur n'allait pas entrer de mots aussi long que ça, car dans mon cas d'utilisations les paragraphes contiennent que du texte normal (en français quoi, pas de code) j'ai fait la méthode juste pour simplifier l'écriture de l'utilisateur.
    C'est aussi pour ça que ma méthode ne gère pas la hauteur maximum.
    Mais il est vrai que dans un cas d'utilisation plus général, la méthode que tu proposes semble bien plus appropriée.

    Qu'en est-il pour les performances ?
    Car je remarque que tu utilises beaucoup de classes (et de méthode) liée au travail graphique qui en général sont assez lourdes au niveau traitement. Dans la mienne, les fonctions sont quasiment toute sur le travail de chaine de caractères, mis à part drawLine et FontMetrics.stringWidth.

  8. #8
    Membre expert
    Avatar de natha
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    2 346
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2006
    Messages : 2 346
    Points : 3 083
    Points
    3 083
    Par défaut
    Citation Envoyé par FabaCoeur Voir le message
    Qu'en est-il pour les performances ?
    J'ai optimisé ma méthode pour qu'elle n'essaie pas d'écrire du texte s'il dépasse. Dans mon cas d'utilisation elle peut être appelée 200x durant un paint sans le moindre problème.
    En gros, même si ma méthode était plus lente que la tienne, elle n'aura pas un impact sur les performances globales de ton programme.
    De toute façon il n'y a pas d'autre moyen de gérer une coupure de lignes et mots proprement.

  9. #9
    Membre actif
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    433
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 433
    Points : 240
    Points
    240
    Par défaut
    Citation Envoyé par natha
    J'ai optimisé ma méthode pour qu'elle n'essaie pas d'écrire du texte s'il dépasse
    Mais si une phrase du paragraphe est trop longue, est ce que ta méthode rajoute un retour à la ligne? Car cette fonctionnalité me semble primordiale.
    Je suis désolé mais je n'arrive vraiment pas à comprendre son implémentation, il y a vraiment trop de classes qui me sont inconnues.

  10. #10
    Membre expert
    Avatar de natha
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    2 346
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2006
    Messages : 2 346
    Points : 3 083
    Points
    3 083
    Par défaut
    exemple :

    Texte original :

    Il s'appelle Pierrot, c'est un joyeux luron.

    Transformation 1
    ___________

    Il s'appelle
    Pierrot, c'est
    un joyeux
    luron.


    Transformation 2 (dans le même genre)

    _____

    Il s'ap
    pelle
    Pierrot
    , c'est
    un jo
    yeux
    luron.

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

Discussions similaires

  1. Optimisation d'une fonction non convexe
    Par Kevin_18 dans le forum Mathématiques
    Réponses: 4
    Dernier message: 06/08/2008, 09h40
  2. Réponses: 3
    Dernier message: 14/06/2008, 19h15
  3. Optimisation d'une fonction
    Par BNS dans le forum C++
    Réponses: 7
    Dernier message: 15/12/2007, 22h25
  4. Réponses: 6
    Dernier message: 27/06/2007, 16h44
  5. Réponses: 4
    Dernier message: 18/01/2006, 10h33

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