Partage
  • Partager sur Facebook
  • Partager sur Twitter

[JAVA] Un editeur de texte à coloration syntaxique

problème avec la coloration syntaxique

Sujet résolu
    3 janvier 2008 à 16:15:32

    <question>
    Bonjour,

    Voila mon problème : je travail actuellement sur un TP pour mes cours qui consiste à programmer en JAVA un éditeur de texte avec coloration syntaxique des différents langages de programmation (genre notepad++).

    Pour le moment l'éditeur fonctionne plutot bien, il ouvre et enregistre des fichiers textes sans problème mais c'est la suite sur laquelle je bloque vraiment un max ! Cela fait un bon moment que je cherche sur différents sites mais pas moyen de trouver une explication clair pour m'aider à mettre en place ce système de coloration syntaxique.
    Ce que je sais c'est qu'il est necessaire de fonctionner non pas avec un JTextArea mais avec un JtextPane (ou JEditorPane ???). J'ai aussi entendu parlé des EditorKit mais je ne sais pas exactement quel est leur fonctionnement et à quoi ils servent...

    Bref je patauge un peu (qui a dit "beaucoup" ?!). Donc ma question est la suivante : Quel est le principe de fonctionnement d'un système de coloration syntaxique en JAVA, quels sont les composants a utiliser et éventuellement où pourrais-je trouver des informations répondant à mon problème ?

    Merci d'avance.
    • Partager sur Facebook
    • Partager sur Twitter
      3 janvier 2008 à 20:12:47

      voila un vieu code que j'utilisait. je pense qu'il fonctionne pour n'importe qu'il JTextComponent

      1. final JTextComponent jtextComponent = ...
      2. jtextComponent.setDocument( new DefaultStyledDocument(){
      3.         public void insertString(int arg0, String arg1, AttributeSet arg2) throws BadLocationException
      4.         {
      5.                 super.insertString(arg0, arg1, arg2);
      6.                 colorise(jtextComponent);              
      7.         }
      8.         public void remove(int arg0, int arg1) throws BadLocationException
      9.         {
      10.                 super.remove(arg0, arg1);
      11.                 colorise(jtextComponent);              
      12.         }
      13. });

      et la méthode colorise
      1. String[] words;
      2. javax.swing.text.Style[] styles;
      3. public void colorise(JTextComponent comp) throws BadLocationException
      4.   {
      5.           if(words.length<styles.length) throw new ArrayIndexOutOfBoundsException();
      6.           String content = null;
      7.           try {
      8.               Document d = comp.getDocument();
      9.               content = d.getText(0, d.getLength());
      10.           } catch (BadLocationException e) {
      11.               return;
      12.           }
      13.           ((DefaultStyledDocument)comp.getDocument()).setCharacterAttributes(0, content.length()-1, normal, true);
      14.           for(int i=0;i<words.length;i++)
      15.           {
      16.                   pattern = Pattern.compile(words[i],Pattern.MULTILINE);
      17.                   matcher = pattern.matcher(content);
      18.                   while(matcher.find())
      19.                   {
      20.                           //System.out.println((matcher.start())+","+( matcher.end()-matcher.start()));
      21.                           if(!out[i])
      22.                                   ((DefaultStyledDocument)comp.getDocument()).setCharacterAttributes(matcher.start(), matcher.end()-matcher.start(), styles[i], false);
      23.                           else
      24.                                   ((DefaultStyledDocument)comp.getDocument()).setCharacterAttributes(matcher.start()+1, matcher.end()-matcher.start()-2, styles[i], false);
      25.                           }
      26.           }
      27.   }



      et voila par exemple les tableaux words et styles pour un éditeur latex (très incomplet)

      1. import javax.swing.text.*;
      2. Style[] styles = new Style[4];
      3. static
      4.   {
      5.           StyleContext sc = new StyleContext();
      6.           normal = sc.addStyle("normal", null);
      7.           styles[0]= sc.addStyle("backslash", null);
      8.           styles[0].addAttribute(StyleConstants.Foreground, new Color(125,125,255));
      9.           styles[0].addAttribute(StyleConstants.FontSize, Integer.valueOf(JLatexEditor.getProperty("fontSize"))-1);
      10.           styles[0].addAttribute(StyleConstants.FontFamily, "Courier New");
      11.           //styles[0].addAttribute(StyleConstants.Bold, true);
      12.           styles[1]= sc.addStyle("parantese", null);
      13.           styles[1].addAttribute(StyleConstants.Foreground, new Color(175,175,255));
      14.           styles[1].addAttribute(StyleConstants.FontSize, Integer.valueOf(JLatexEditor.getProperty("fontSize"))-1);
      15.           styles[1].addAttribute(StyleConstants.FontFamily, "Courier New");
      16.           styles[1].addAttribute(StyleConstants.Italic, true);
      17.           styles[2]= sc.addStyle("crochet", null);
      18.           styles[2].addAttribute(StyleConstants.Foreground, new Color(205,187,135));
      19.           styles[2].addAttribute(StyleConstants.FontSize, Integer.valueOf(JLatexEditor.getProperty("fontSize"))-1);
      20.           styles[2].addAttribute(StyleConstants.FontFamily, "Courier New");
      21.           styles[2].addAttribute(StyleConstants.Underline, true);
      22.           styles[3]= sc.addStyle("dollar", null);
      23.           styles[3].addAttribute(StyleConstants.Foreground, Color.black);
      24.           styles[3].addAttribute(StyleConstants.FontSize, Integer.valueOf(JLatexEditor.getProperty("fontSize"))-1);
      25.           styles[3].addAttribute(StyleConstants.FontFamily, "Courier New");
      26.           styles[3].addAttribute(StyleConstants.Bold, true);
      27.           styles[4]= sc.addStyle("paranthese", null);
      28.           styles[4].addAttribute(StyleConstants.Foreground, Color.orange);
      29.           styles[4].addAttribute(StyleConstants.FontSize, Integer.valueOf(JLatexEditor.getProperty("fontSize"))-1);
      30.           styles[4].addAttribute(StyleConstants.FontFamily, "Courier New");
      31.           styles[4].addAttribute(StyleConstants.Italic, true);
      32.   }
      33.   private static String[] words = {
      34.           "\\\\[A-Za-z0-9_,.#]+(\\[.+\\])?(\\{[^\\n\\r\\}\\{]+\\}){0,2}",
      35.           "\\[.+\\]",
      36.           "\\{[^\\n\\r\\}\\{]+\\}",
      37.           "\\$[^\\n\\r\\$]+\\$",
      38.           "(\\\\left(\\(|\\[|\\{))|(\\\\right(\\)|\\]|\\}))"};


      en espérant que ça t'aide
      • Partager sur Facebook
      • Partager sur Twitter
        3 janvier 2008 à 23:32:03

        Merci à toi. Il va falloir que je me penche sérieusement sur ton code pour bien comprendre mais merci ^^'. Pour tout te dire je suis plutot débutant en JAVA.
        • Partager sur Facebook
        • Partager sur Twitter
          3 janvier 2008 à 23:50:15

          Tu as combien de mois en Java derrière toi et tu fais quoi comme formation ?

          Sinon, si tu as le choix des composants et que tu peux rajouter des libs. regarde JXEditorPane de
          ici.
          Je ne sais pas si il est bien mais d'autre de leurs composants sont très très bien...
          • Partager sur Facebook
          • Partager sur Twitter
            4 janvier 2008 à 10:43:57

            Je suis en seconde année de BTS Info-Gestion en option developpeur d'appli. Donc j'ai tout juste 3 mois de JAVA derriere mois (en comptant 4h de TP/semaine + du boulot perso). Le truc c'est que ma prof a déjà fait un programme comme celui la mais qu'elle n'est pas foutu de se souvenir du principe de son appli...
            Donc en gros je ne suis pas vraiment aidé pendant les TP et je passe des heures a chercher sur le net sans rien trouver de bien clair pour mon petit cerveau ^^' .

            Vous ne sauriez pas par hasard s'il existe un tuto bien fait sur le sujet ou sur quelque chose qui s'en rapproche ? Mon vrai problème est de savoir quel est le principe globale en fait (ou l'algo si vous préférez) ...
            • Partager sur Facebook
            • Partager sur Twitter
              4 janvier 2008 à 13:00:23

              le principe est assez simple.

              tout JTextComponent possede un Document qui contient le texte.
              Toute modification au texte passe néssessairement pas la methode insertString ou remove

              donc en surchargeant ces méthodes je suis certain que colorise est appelé à chaque modification du texte, que se soit par l'utilisateur ou par le programme

              J'utilise un DefaultStyledDocument car il permet de changer le style de certaines parties du texte.
              Grace à la methode setCharacterAttributes(int offset, int length, javax.swing.text.Style, boolean replace);

              offset -> position du début de la partie de la chaîne sur laquelle le style sera appliqué
              length -> longueur de la partie de la chaîne sur laquelle le style sera appliqué

              javax.swing.text.Style -> le style
              1. // d'abord on crée un objet StyleContext
              2. // c'est à lui que l'on attribue des styles
              3. // le style normal, on ne lui modifie rien...
              4. Style normal = sc.addStyle("normal", null);
              5. // voila un deuxième style
              6. Style style = sc.addStyle("style", null);
              7. // on peut modifier la couleur de la police
              8. style.addAttribute(StyleConstants.Foreground, new Color(125,125,255));
              9. // la couleur de fond (surlignement)
              10. style.addAttribute(StyleConstants.Background, new Color(255,125,125));
              11. // la taille de la police
              12. style.addAttribute(StyleConstants.FontSize, 11);
              13. // la police
              14. style.addAttribute(StyleConstants.FontFamily, "Courier New");
              15. // mettre en gras
              16. style.addAttribute(StyleConstants.Bold, true);
              17. // mettre en italique
              18. style.addAttribute(StyleConstants.Italic, true);
              19. // mettre en souligné
              20. style.addAttribute(StyleConstants.Underline, true);


              le dernier argument (replace) indique s'il remplace completement le style précédent, ou si les attributs qu'il ne défini pas lui-même sont repris au style précédent

              pour voir toutes les constantes a modifier fais un tour dans la javadoc de StyleConstants

              1. javax.swing.text.Style normal;
              2. String[] words;
              3. javax.swing.text.Style[] styles;
              4. boolean[] out;
              5. public void colorise(JTextComponent comp) throws BadLocationException
              6.   {
              7.           if(words.length<styles.length) throw new ArrayIndexOutOfBoundsException();
              8.           // on récupère le texte dans une chaîne
              9.           String content = null;
              10.           try {
              11.               Document d = comp.getDocument();
              12.               content = d.getText(0, d.getLength());
              13.           } catch (BadLocationException e) {
              14.               return;
              15.           }
              16.           // on met tout le document en style normal
              17.           ((DefaultStyledDocument)comp.getDocument()).setCharacterAttributes(0, content.length()-1, normal, true);
              18.           // on fais une boucle
              19.           // pour chaque expression du tableau word
              20.           // on cherche ses itérations, et on l'associe à un style du tableau styles
              21.           for(int i=0;i<words.length;i++)
              22.           {
              23.                   // on crée un pattern, un objet qui peut interpréter une chaine utilisant les expressions ordinaires
              24.                   pattern = Pattern.compile(words[i],Pattern.MULTILINE);
              25.                   // on crée un matcher, qui va recharcher l'expression du pattern dans le texte
              26.                   matcher = pattern.matcher(content);
              27.                   while(matcher.find())
              28.                   {
              29.                           // le tableau out précise si l'on doit exclure le premier et le dernier caractère de la chaîne
              30.                           if(!out[i])
              31.                                   ((DefaultStyledDocument)comp.getDocument()).setCharacterAttributes(matcher.start(), matcher.end()-matcher.start(), styles[i], false);
              32.                           else
              33.                                   ((DefaultStyledDocument)comp.getDocument()).setCharacterAttributes(matcher.start()+1, matcher.end()-matcher.start()-2, styles[i], false);
              34.                           }
              35.           }
              36.   }


              En espérant que sa t'aide ;)

              EDIT -> faute dans ma méthode...
              • Partager sur Facebook
              • Partager sur Twitter
                4 janvier 2008 à 15:54:22

                Humm. Bon j'ai essayer d'adapter ca à mon code mais ca réel succes à vrai dire ^^'.

                J'ai plusieurs questions :
                - Tu dis "Toute modification au texte passe néssessairement pas la methode insertString ou remove" donc il n'y a pas d'évenement clavier ou autre à gérer ?
                - Ton code pourrais-t-il fonctionner avec un JTextPane ?
                - Je ne comprend pas bien la structure de ce que tu m'as montré : qu'elles sont les classes ? où vont les méthodes ? ou sont les mots clefs du langage à mettre en évidence ?

                Comme vous pouvez le voir ce n'est pas encore bien clair dans ma tête. En tout cas meci beaucoup de vous interresser à mon problème ^^
                • Partager sur Facebook
                • Partager sur Twitter
                  4 janvier 2008 à 16:34:36

                  ben tu peu faire par exemple une classe étendant de ton JTextPane

                  1. import java.util.regex.*;
                  2. import javax.swing.JTextPane;
                  3. import javax.swing.text.*;
                  4. public abstract class ColorisedTextPane extends JTextPane {
                  5.         protected Style normal;
                  6.         protected String[] words;
                  7.         protected Style[] styles;
                  8.         protected boolean[] out;
                  9.         public ColorisedTextPane()
                  10.         {
                  11.                 super();
                  12.                 this.setDocument(new DefaultStyledDocument()
                  13.                 {
                  14.                         public void insertString(int arg0, String arg1, AttributeSet arg2) throws BadLocationException
                  15.                 {
                  16.                         super.insertString(arg0, arg1, arg2);
                  17.                         colorise();              
                  18.                 }
                  19.                 public void remove(int arg0, int arg1) throws BadLocationException
                  20.                 {
                  21.                         super.remove(arg0, arg1);
                  22.                         colorise();              
                  23.                 }
                  24.             });
                  25.                 initStyles();
                  26.         }
                  27.         protected abstract void initStyles();
                  28.         private void colorise() throws BadLocationException
                  29.         {
                  30.                 if(words.length<styles.length) throw new ArrayIndexOutOfBoundsException();
                  31.                   // on récupère le texte dans une chaîne
                  32.                   String content = null;
                  33.                   try {
                  34.                       Document d = this.getDocument();
                  35.                       content = d.getText(0, d.getLength());
                  36.                   } catch (BadLocationException e) {
                  37.                       return;
                  38.                   }
                  39.                   // on met tout le document en style normal
                  40.                   ((DefaultStyledDocument)this.getDocument()).setCharacterAttributes(0, content.length()-1, normal, true);
                  41.                   // on fais une boucle
                  42.                   // pour chaque expression du tableau word
                  43.                   // on cherche ses itérations, et on l'associe à un style du tableau styles
                  44.                   for(int i=0;i<words.length;i++)
                  45.                   {
                  46.                           // on crée un pattern, un objet qui peut interpréter une chaine utilisant les expressions ordinaires
                  47.                           Pattern pattern = Pattern.compile(words[i],Pattern.MULTILINE);
                  48.                           // on crée un matcher, qui va recharcher l'expression du pattern dans le texte
                  49.                           Matcher matcher = pattern.matcher(content);
                  50.                           while(matcher.find())
                  51.                           {
                  52.                                   // le tableau out précise si l'on doit exclure le premier et le dernier caractère de la chaîne
                  53.                                   if(!out[i])
                  54.                                           ((DefaultStyledDocument)this.getDocument()).setCharacterAttributes(matcher.start(), matcher.end()-matcher.start(), styles[i], false);
                  55.                                   else
                  56.                                           ((DefaultStyledDocument)this.getDocument()).setCharacterAttributes(matcher.start()+1, matcher.end()-matcher.start()-2, styles[i], false);
                  57.                                   }
                  58.                   }
                  59.           }
                  60. }


                  après il ne te reste qu'a créer une classe par language à coloriser
                  par exemple

                  1. import java.awt.Color;
                  2. import javax.swing.text.*;
                  3. public class LatexTextPane extends ColorisedTextPane  {
                  4.         protected void initStyles() {
                  5.                   words = new String[]{"\\\\[A-Za-z0-9_,.#]+(\\[.+\\])?(\\{[^\\n\\r\\}\\{]+\\}){0,2}",
                  6.                           "\\[.+\\]",
                  7.                           "\\{[^\\n\\r\\}\\{]+\\}",
                  8.                           "\\$[^\\n\\r\\$]+\\$",
                  9.                           "(\\\\left(\\(|\\[|\\{))|(\\\\right(\\)|\\]|\\}))"};
                  10.                   StyleContext sc = new StyleContext();
                  11.           normal = sc.addStyle("normal", null);
                  12.           styles[0]= sc.addStyle("backslash", null);
                  13.           styles[0].addAttribute(StyleConstants.Foreground, new Color(125,125,255));
                  14.           styles[0].addAttribute(StyleConstants.FontSize, new Integer(11));
                  15.           styles[0].addAttribute(StyleConstants.FontFamily, "Courier New");
                  16.           //styles[0].addAttribute(StyleConstants.Bold, true);
                  17.           styles[1]= sc.addStyle("parantese", null);
                  18.           styles[1].addAttribute(StyleConstants.Foreground, new Color(175,175,255));
                  19.           styles[1].addAttribute(StyleConstants.FontSize, new Integer(11));
                  20.           styles[1].addAttribute(StyleConstants.FontFamily, "Courier New");
                  21.           styles[1].addAttribute(StyleConstants.Italic, new Boolean(true));
                  22.           styles[2]= sc.addStyle("crochet", null);
                  23.           styles[2].addAttribute(StyleConstants.Foreground, new Color(205,187,135));
                  24.           styles[2].addAttribute(StyleConstants.FontSize, new Integer(11));
                  25.           styles[2].addAttribute(StyleConstants.FontFamily, "Courier New");
                  26.           styles[2].addAttribute(StyleConstants.Underline, new Boolean(true));
                  27.           styles[3]= sc.addStyle("dollar", null);
                  28.           styles[3].addAttribute(StyleConstants.Foreground, Color.black);
                  29.           styles[3].addAttribute(StyleConstants.FontSize, new Integer(11));
                  30.           styles[3].addAttribute(StyleConstants.FontFamily, "Courier New");
                  31.           styles[3].addAttribute(StyleConstants.Bold, new Boolean(true));
                  32.           styles[4]= sc.addStyle("paranthese", null);
                  33.           styles[4].addAttribute(StyleConstants.Foreground, Color.orange);
                  34.           styles[4].addAttribute(StyleConstants.FontSize, new Integer(11));
                  35.           styles[4].addAttribute(StyleConstants.FontFamily, "Courier New");
                  36.           styles[4].addAttribute(StyleConstants.Italic, new Boolean(true));
                  37.           out = new boolean[]{false,
                  38.                           true,
                  39.                           true,
                  40.                           false,
                  41.                           false};
                  42.         }
                  43. }
                  • Partager sur Facebook
                  • Partager sur Twitter
                    4 janvier 2008 à 18:19:44

                    J'ai fait ce que tu m'as dis, ca passe niquel à la compil' (je suis sur blueJ 2.2.0 au fait).
                    Mais (et oui dsl^^') il plante à l'éxecution et me donne ce message dans la console :

                    1.         at LatexTextPane.initStyles(LatexTextPane.java:17)
                    2.         at ColorisedTextPane.<init>(ColorisedTextPane.java:32)
                    3.         at LatexTextPane.<init>(LatexTextPane.java:4)
                    4.         at GRAPHNOTEPAD.<init>(GRAPHNOTEPAD.java:37)
                    5.         at EVENTNOTEPAD.<init>(EVENTNOTEPAD.java:17)
                    6.         at EXECNOTEPAD.main(EXECNOTEPAD.java:6)


                    ... :-°

                    EDIT:
                    C'est bon j'ai trouvé : c'était le tableau de styles qui n'était pas bien déclaré.

                    1. protected Style[] styles = new Style[5];
                    • Partager sur Facebook
                    • Partager sur Twitter
                      4 janvier 2008 à 21:00:19

                      Alors là tu n'as pas a t'escuser... Je te remercie vraiment beaucoup pour ton aide. Enfin j'arrive à m'en sortir.
                      Merci merci merci :)
                      • Partager sur Facebook
                      • Partager sur Twitter
                        14 février 2008 à 13:33:41

                        Je remonte le sujet car il m'interesse, mais je ne comprends pas tout. Le JTextComponent il vient d'ou par exemple ?
                        • Partager sur Facebook
                        • Partager sur Twitter

                        [JAVA] Un editeur de texte à coloration syntaxique

                        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                        × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                        • Editeur
                        • Markdown