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 :

Méthode pour un LineBreaker


Sujet :

Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre actif
    Homme Profil pro
    Inscrit en
    Septembre 2013
    Messages
    149
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2013
    Messages : 149
    Par défaut Méthode pour un LineBreaker
    Bonjour,

    Je débute dans l'utilisation des méthodes et j'ai un petit problème avec ma première méthode disons "complexe". Enfin je veux dire par là que ce n'est plus du niveau de la méthode pour faire une somme!^^

    Bref, je voudrais créer une méthode qui me permettrais de mettre en forme un texte en une seule ligne...avec beaucoup d'arguments. J'ai très bien réussi à utiliser le procédé proposé par la doc et ça fonctionne très bien. Maintenant je voudrais faire en sorte qu'il soit écrit une seule fois pour pouvoir le réutiliser à volonté vu que je devrais beaucoup l'utiliser dans mon programme. Voici mon 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
    public class TextBuilder {
     
    	private LineBreakMeasurer lineMeasurer;
    	private int paragraphStart;
    	private int paragraphEnd;
     
    	public void autoLineBreaker(JPanel panel, AttributedString string, Hashtable<TextAttribute, Object> map, String police, Float size, int posY, Graphics g){
     
    		map.put(TextAttribute.FAMILY,  police);
    		map.put(TextAttribute.SIZE,  size);
     
     
    	        Graphics2D g2d = (Graphics2D)g;
    	        g2d.setRenderingHint(
    	                RenderingHints.KEY_TEXT_ANTIALIASING,
    	                RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
     
    	        if (lineMeasurer == null) {
    	            AttributedCharacterIterator paragraph = string.getIterator();
    	            paragraphStart = paragraph.getBeginIndex();
    	            paragraphEnd = paragraph.getEndIndex();
    	            FontRenderContext frc = g2d.getFontRenderContext();
    	            lineMeasurer = new LineBreakMeasurer(paragraph, frc);
    	        }
     
    	        float breakWidth = (float)panel.getSize().width;
    	        float drawPosY = posY;
    	        lineMeasurer.setPosition(paragraphStart);
     
     
    	        while (lineMeasurer.getPosition() < paragraphEnd) {
     
    	            TextLayout layout = lineMeasurer.nextLayout(breakWidth);
     
    	            float drawPosX = layout.isLeftToRight()
    	                ? 0 : breakWidth - layout.getAdvance();
     
    	            drawPosY += layout.getAscent();
     
    	            layout.draw(g2d, drawPosX, drawPosY);
     
    	            drawPosY += layout.getDescent() + layout.getLeading();
    	        }
    	    }
     
    	}
    Et donc pour l'appeler:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    objet.autoLineBreaker(panel, string, map, "Arial", 15.0, 0, g)
    (J'ai ajouté un argument posY car j'en aurais besoin plus tard...)

    Pour commencer, si vous avez quelque remarque qui soit sur mon code je veux bien l'entendre afin de pouvoir l'améliorer!

    Ensuite, voici mon problème: quand j'essaie d'appliquer ma méthode sur un panel, eclipse me répond naturellement que ma méthode n'est pas définie pour le type "nomDuPanel". Comment faire pour la définir de manière à ce que ça fonctionne?

    Et pour finir, l'arguments Graphics g est essentiel mais comment faire pour ne pas avoir besoin de l'appeler dans la classe où je souhaite invoquer ma méthode?

    J'espère que vous pourrez m'aider, merci d'avance!

  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 : 55
    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
    Billets dans le blog
    2
    Par défaut
    Salut,

    ne mélanges pas la configuration (AttributedString, coordonnées x et y), la layout (le calcul que tu fais dans autoLineBreaker) et le dessin (les manipulations de Graphics) : tu peux créer tes TextLayout uniquement avec les dimensions du panel et l'AttributedString (le FontRendererContext, tu peux le créer par new FontRenderContext(null, true, true)), donc seulement quand celles-ci changent (par java.awt.event.ComponentListener) ou quand AttributedString (qui devient juste une variable d'instance de TextBuilder) change, ou éventuellement la première fois que tu dessines (et que donc la liste n'a pas encore été créée)

    Tu ajoutes une méthode draw(Graphics) dans TextBuilder (que tu appeleras dans paint(Graphics) du JPanel), dans laquelle tu parcours la liste de TextLayout (prévois de la créer également dans cette méthod, s'il elle n'existe pas encore . et tu invoques draw de chaque textLayouts, en incrémentant ton posY.

    D'autre part, tu n'a pas besoin de passer une police et une map d'attributs en arguments, l'AttributedString étant déjà stylés (d'ailleurs dans ton code, tu t'en sers nulle part.

    Tu peux ajouter plusieurs textes au même panel en y ayant une List<TextBuilder>...

    Tu peux même te faire une classe StyledTextPanel qui étend JPanel avec une méthode add(AttributedString text, int x, int y) qui fait un textBuilderList.add(new TextBuilder(text,x,y)) suivi d'un repaint...
    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
    Membre actif
    Homme Profil pro
    Inscrit en
    Septembre 2013
    Messages
    149
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2013
    Messages : 149
    Par défaut
    Tu pourrais me montrer un exemple s'il te plait? Je ne vois pas trop où tu veux en venir avec le draw(Graphics)...

  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 : 55
    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
    Billets dans le blog
    2
    Par défaut
    Je te donne un exemple de principe :

    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
    public class TextBuilder {
     
        private AttributedString string;
        private List<TextLayout> layouts;
        private int x;
        private int y;
        private JPanel panel;
     
        public TextBuilder(AttributedString string, int x, int y, JPanel panel) {
            this.string=string;
            this.panel=panel;
            this.x=x;
            this.y=y;
            panel.addComponentListener(new ComponentAdapter() {
                public void componentResized(ComponentEvent event) {
                     autoLineBreaker(); // on recalcule le layout
                }
            });
     
        }
     
        public void setString(AttributedString string) {
            this.string=string;
            autoLineBreaker(); // on recalcule le layout
            panel.repaint();
        }
     
        public void setPosition(int x, int y) {
            this.x=x;
            this.y=y;
        } 
     
        // la j'ai juste reprise ta méthode, sans en modifier le traitement, en enlevant juste ce qui n'était pas nécessaire
        // on pourrait également profiter de cette méthode pour savoir les dimensions du texte
         private void autoLineBreaker(){
     
    	AttributedCharacterIterator paragraph = string.getIterator();
    	int paragraphStart = paragraph.getBeginIndex();
    	int paragraphEnd = paragraph.getEndIndex();
    	FontRenderContext frc = new FontRenderContext(null, true, true); // rendu haute qualité
    	LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(paragraph, frc); 
     
            float breakWidth = (float)panel.getSize().width-x;
    	lineMeasurer.setPosition(paragraphStart);
     
            layouts=new ArrayList<>();
            while (lineMeasurer.getPosition() < paragraphEnd) {
     
    	     layouts.add(lineMeasurer.nextLayout(breakWidth)); // ne tient pas compte des \n
     
             }
         }
     
         public void draw(Graphics2D g2d) {
              Object memTextAntiAlias = g2d.getRenderingHint(
    	                RenderingHints.KEY_TEXT_ANTIALIASING);
              g2d.setRenderingHint(
    	                RenderingHints.KEY_TEXT_ANTIALIASING,
    	                RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
     
              if ( layouts==null ) autoLineBreaker();
     
     float breakWidth = (float)panel.getSize().width;
     
    	  float drawPosY = y;
     
     
              for(TextLayout layout : layouts) {
     
    	            float drawPosX = x + (layout.isLeftToRight()
    	                ? 0 : breakWidth - layout.getAdvance()); 
     
                        drawPosY += layout.getAscent();
     
    	            layout.draw(g2d, drawPosX, drawPosY);
     
    	            drawPosY += layout.getDescent() + layout.getLeading();
     
              }
     
              g2d.setRenderingHint(
    	                RenderingHints.KEY_TEXT_ANTIALIASING,
    	                memTextAntiAlias );
         }
     
    }
    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
    public class StyledTextPanel extends JPanel {
     
    	private List<TextBuilder> texts;
     
        public StyledTextPanel() {
             texts=new ArrayList<>();
        }
     
        public void addText(AttributedString text, int x, int y) {
            texts.add(new TextBuilder(text, x, y, this));
            repaint();
        }
     
        public void paint(Graphics g) {
        	super.paint(g);
               for(TextBuilder text : texts) {
                   text.draw((Graphics2D) g);
               }
        }
     
        public static void main(String[] args) {
            JFrame frame=new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
            StyledTextPanel panel =  new StyledTextPanel();
            panel.setBorder(BorderFactory.createLineBorder(Color.RED));
            panel.setBackground(Color.YELLOW);
     
            panel.addText(new AttributedString("xxxx xxxx xxxx xxxxxx xxx xxxxxx xxxxx xxxxx"),10,10);
            panel.addText(new AttributedString("aaaaa  aa aaaa aaaaa aaaaaaa aaa aaaaa aaa"),10,50);
     
            frame.getContentPane().add(panel);
     
            frame.setSize(200,200);
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
    	}
     
    }
    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
    Membre actif
    Homme Profil pro
    Inscrit en
    Septembre 2013
    Messages
    149
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2013
    Messages : 149
    Par défaut
    Merci beaucoup ton exemple est très clair. Je testerais ce week-end.

  6. #6
    Membre actif
    Homme Profil pro
    Inscrit en
    Septembre 2013
    Messages
    149
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2013
    Messages : 149
    Par défaut
    J'ai testé et j'ai rencontré des erreurs. Par exemple je me suis rendu compte que ton "panel" générait une erreur ainsi que ton "autoLineBreaker();" pour recalculer le layout. Il faudra que je me re-penche sur ton code pour mieu le comprendre.

    Merci pour le second code, lui m'a bien aidé. C'est vrai que c'est plus pratique ainsi.

    Je dois proposer une version dès Lundi donc pour l'instant j'ai copié-collé ma méthode à chaque fois que j'en avais besoin, j’optimiserais mon logiciel plus tard!^^

Discussions similaires

  1. Meilleur méthode pour stocker mes données
    Par cyberlewis dans le forum Windows
    Réponses: 6
    Dernier message: 03/07/2004, 11h53
  2. Réponses: 3
    Dernier message: 24/06/2004, 11h23
  3. [C#] Une seule méthode pour plusieurs composants
    Par niPrM dans le forum Windows Forms
    Réponses: 8
    Dernier message: 01/06/2004, 14h41
  4. [SWING][THREAD]Méthodes pour afficher une Frame
    Par pompidouwa dans le forum Agents de placement/Fenêtres
    Réponses: 3
    Dernier message: 05/05/2004, 10h35
  5. Fonction/méthode pour obtenir l'IP de la machine
    Par sirex007 dans le forum Web & réseau
    Réponses: 3
    Dernier message: 10/04/2003, 14h36

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