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 :

Problème avec la classe DefaultStyledDocument et la méthode setCharacterAttributes


Sujet :

AWT/Swing Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Juillet 2008
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Juillet 2008
    Messages : 15
    Par défaut Problème avec la classe DefaultStyledDocument et la méthode setCharacterAttributes
    Bonjour

    Après avoir épuisé toutes les pistes... je me remets à vous pour m'aider à trouver une solution !

    J'ai créé un éditeur qui modifie la couleur des mots suivant le contexte dans lequel ils se trouvent.
    Jusqu'à là, rien d'extraordinaire !
    J'ai mon parseur, qui analyse le texte que tape le programmeur et ensuite, j'utilise la méthode setCharacterAttributes pour affecter la couleur. Pour cela, je passe par un thread.

    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
     
    public class AtelierDocument extends DefaultStyledDocument {
     
    	public void setCharacterAttributes(List<Style> list) {
     
    		try {
    			writeLock();
    			List<Style> styles = StyleBuffer.retourneStyles();
    			while (!styles.isEmpty()) {
    				Style style = styles.get(0);
    				styles.remove(style);
    				int taille = style.getTaille();
    				if (taille == -1)
    					taille = getLength();
    				if (style.getPosition() > getLength())
    					continue;
    				if (taille != 0) {
    					setCharacterAttributes2(style.getPosition(), taille, style.getStyle(), true);
    				}
    			}
    		} finally {
    			writeUnlock();
    		}
    	}
     
    	private void setCharacterAttributes2(int offset, int length, AttributeSet s, boolean replace) {
    		if (length == 0) {
    			return;
    		}
     
    		DefaultDocumentEvent changes = new DefaultDocumentEvent(offset, length, DocumentEvent.EventType.CHANGE);
     
    		// split elements that need it
    		buffer.change(offset, length, changes);
     
    		AttributeSet sCopy = s.copyAttributes();
     
    		// PENDING(prinz) - this isn't a very efficient way to iterate
    		int lastEnd = Integer.MAX_VALUE;
    		for (int pos = offset; pos < (offset + length); pos = lastEnd) {
    			Element run = getCharacterElement(pos);
    			lastEnd = run.getEndOffset();
    			if (pos == lastEnd) {
    				// offset + length beyond length of document, bail.
    				break;
    			}
    			MutableAttributeSet attr = (MutableAttributeSet) run.getAttributes();
    			changes.addEdit(new AttributeUndoableEdit(run, sCopy, replace));
    			if (replace) {
    				attr.removeAttributes(attr);
    			}
    			attr.addAttributes(s);
    		}
    		changes.end();
    		fireChangedUpdate(changes);
    		fireUndoableEditUpdate(new UndoableEditEvent(this, changes));
     
    	}
    }
    Le code du thread :

    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
     
    	public static void appliquer(final int nombre, final int decal) {
    		SwingUtilities.invokeLater(new Runnable() {
     
    			public void run() {
    				try {
    					if (appliquer)
    						document.setCharacterAttributes(StyleBuffer.retourneStyles());
    					else
    						StyleBuffer.effacerStyle();
    				} catch (Exception e) {
    					System.out.println("Erreur application des styles");
    				}
    			}
     
    		});
    	}
    ça fonctionne presque normalement...
    Mais dés que j'utilise un undoManager pour filtrer les changements de styles, rien ne va plus !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    			undoManager = new UndoManager()//;
    			{
    				public synchronized boolean addEdit(UndoableEdit anEdit) {
    					if (anEdit instanceof AbstractDocument.DefaultDocumentEvent) {
    						AbstractDocument.DefaultDocumentEvent de = (AbstractDocument.DefaultDocumentEvent) anEdit;
    						if (de.getType() == DocumentEvent.EventType.CHANGE) {
    							return false;
    						}
    					}
    					return super.addEdit(anEdit);
    				}
     
    			};
    En utilisant le undo/redo, rapidement j'ai le curseur qui disparait et ensuite, l'affichage de la zone texte se bloque ou mon texte est décalé.

    Après plusieurs tests, je ne pense pas que mon problème soit dû à l'utilisation des threads. C'est la méthode setcharacterAttributes qui semble se mélanger les pinceaux à un moment que je n'arrive pas à déterminer !

    Voici le l'adresse de mon code.
    https://linotte.dev.java.net/source/...linotte/frame/

    Il n'est pas très beau... je sais...

    J'espère qu'une personne trouvera une solution....

    Ronan

  2. #2
    Membre averti
    Inscrit en
    Juillet 2008
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Juillet 2008
    Messages : 15
    Par défaut Présentation du problème plus simplement !
    Bonjour,

    Voici un exemple que vous pouvez tester pour mieux comprendre mon problème :
    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
     
    import java.awt.*;
    import java.awt.event.*;
    import java.util.regex.*;
     
    import javax.swing.*;
    import javax.swing.event.*;
    import javax.swing.text.*;
    import javax.swing.undo.*;
     
    public class Demo {
     
    	public static SimpleAttributeSet style_error = null;
     
    	@SuppressWarnings("serial")
    	public static void main(String[] args) {
     
    		style_error = new SimpleAttributeSet();
    		StyleConstants.setForeground(style_error, Color.RED);
    		StyleConstants.setBackground(style_error, Color.WHITE);
    		StyleConstants.setItalic(style_error, false);
     
    		final JTextPane textPane = new JTextPaneText();
    		textPane.setPreferredSize(new Dimension(200, 200));
     
    		textPane.setDocument(new DefaultStyledDocument());
     
    		final UndoManager undoManager = new UndoManager() {
    			public synchronized boolean addEdit(UndoableEdit anEdit) {
    				if (anEdit instanceof AbstractDocument.DefaultDocumentEvent) {
    					AbstractDocument.DefaultDocumentEvent de = (AbstractDocument.DefaultDocumentEvent) anEdit;
    					if (de.getType() == DocumentEvent.EventType.CHANGE) {
    						return false;
    					}
    				}
    				return super.addEdit(anEdit);
    			}
    		};
     
    		textPane.getStyledDocument().addUndoableEditListener(new UndoableEditListener() {
    			public void undoableEditHappened(UndoableEditEvent e) {
    				undoManager.addEdit(e.getEdit());
    			}
    		});
     
    		JPanel panel = new JPanel();
    		panel.setLayout(new BorderLayout());
    		panel.add(new JScrollPane(textPane), BorderLayout.CENTER);
     
    		JPanel buttons = new JPanel();
    		panel.add(buttons, BorderLayout.SOUTH);
     
    		JButton undo = new JButton("Undo");
    		undo.addActionListener(new ActionListener() {
    			public void actionPerformed(ActionEvent e) {
    				try {
    					undoManager.undo();
    					textPane.requestFocus();
    				} catch (CannotUndoException ex) {
    				}
    			}
    		});
    		buttons.add(undo);
     
    		JButton redo = new JButton("Redo");
    		redo.addActionListener(new ActionListener() {
    			public void actionPerformed(ActionEvent e) {
    				try {
    					undoManager.redo();
    					textPane.requestFocus();
    				} catch (CannotRedoException ex) {
    				}
    			}
    		});
    		buttons.add(redo);
     
    		JButton style = new JButton("Style");
    		style.addActionListener(new ActionListener() {
    			public void actionPerformed(ActionEvent e) {
    				Pattern p = Pattern.compile("texte");
    				String out = textPane.getText();
    				Matcher matcher = p.matcher(out);
    				while (matcher.find()) {
    					textPane.getStyledDocument().setCharacterAttributes(matcher.start(), matcher.end() - matcher.start(), style_error, true);
    				}
    			}
    		});
    		buttons.add(style);
     
    		JFrame frame = new JFrame("Demo");
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		frame.getContentPane().add(panel);
    		frame.pack();
    		frame.setVisible(true);
    	}
    }
    Lancez cette classe. Pour reproduire mon problème, entrez le texte suivant dans le petit éditeur :
    voici un texte
    sur une nouvelle ligne ce texte
    encore une ligne !
    Ensuite, appuyez sur le bouton Style. il va utilise la méthode setCharacterAttributes pour changer la couleur de toutes les occurrences du mot 'texte'.

    Ensuite, utilisez le bouton redo pour revenir en arrière.

    Vous voyez, ma zone de texte ne fonctionne plus !

    Help

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

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Par défaut
    http://code.google.com/p/jsyntaxpane/

    Ca devrait être un poil plus facile avec çà.
    ++

  4. #4
    Membre averti
    Inscrit en
    Juillet 2008
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Juillet 2008
    Messages : 15
    Par défaut
    Citation Envoyé par sinok Voir le message
    http://code.google.com/p/jsyntaxpane/

    Ca devrait être un poil plus facile avec çà.
    ++
    Bonjour,

    Merci mais ce programme n'est pas compatible avec ce que je veux faire.
    La technique utilisée ici, est d'analyser le texte lors de la frappe de l'utilisateur.
    Mon parseur est bien trop lent... il faudrait attendre 3 secondes par caractère frappé !
    C'est pour cela que j'utilise un thread.

    Sinon, voici une autre version qui plante. vous avez juste à l'exécuter et une trace s'affiche dans la console.
    En fait, dés qu'il y a un retour chariot que j'utilise la méthode setCharactereAttribute , le undo ne fonctionne plus !

    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
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
     
    import java.awt.*;
    import java.awt.event.*;
    import java.util.regex.*;
     
    import javax.swing.*;
    import javax.swing.event.*;
    import javax.swing.text.*;
    import javax.swing.undo.*;
     
    public class Demo {
     
    	public static SimpleAttributeSet style_error = null;
     
    	public static void main(String[] args) {
     
    		style_error = new SimpleAttributeSet();
    		StyleConstants.setForeground(style_error, Color.RED);
    		StyleConstants.setBackground(style_error, Color.WHITE);
    		StyleConstants.setItalic(style_error, false);
     
    		final JTextPane textPane = new JTextPane();
    		textPane.setPreferredSize(new Dimension(200, 200));
     
    		textPane.setDocument(new DefaultStyledDocument());
     
    		final UndoManager undoManager = new UndoManager() {
    			public synchronized boolean addEdit(UndoableEdit anEdit) {
    				if (anEdit instanceof AbstractDocument.DefaultDocumentEvent) {
    					AbstractDocument.DefaultDocumentEvent de = (AbstractDocument.DefaultDocumentEvent) anEdit;
    					if (de.getType() == DocumentEvent.EventType.CHANGE) {
    						return false;
    					}
    				}
    				return super.addEdit(anEdit);
    			}
    		};
     
    		textPane.getStyledDocument().addUndoableEditListener(new UndoableEditListener() {
    			public void undoableEditHappened(UndoableEditEvent e) {
    				undoManager.addEdit(e.getEdit());
    			}
    		});
     
    		JPanel panel = new JPanel();
    		panel.setLayout(new BorderLayout());
    		panel.add(new JScrollPane(textPane), BorderLayout.CENTER);
     
    		JPanel buttons = new JPanel();
    		panel.add(buttons, BorderLayout.SOUTH);
     
    		JButton undo = new JButton("Undo");
    		undo.addActionListener(new ActionListener() {
    			public void actionPerformed(ActionEvent e) {
    				try {
    					undoManager.undo();
    					textPane.requestFocus();
    				} catch (CannotUndoException ex) {
    				}
    			}
    		});
    		buttons.add(undo);
     
    		JButton redo = new JButton("Redo");
    		redo.addActionListener(new ActionListener() {
    			public void actionPerformed(ActionEvent e) {
    				try {
    					undoManager.redo();
    					textPane.requestFocus();
    				} catch (CannotRedoException ex) {
    				}
    			}
    		});
    		buttons.add(redo);
     
    		JButton style = new JButton("Style");
    		style.addActionListener(new ActionListener() {
    			public void actionPerformed(ActionEvent e) {
    				try {
    					Pattern p = Pattern.compile("text");
    					String out = textPane.getDocument().getText(0, textPane.getDocument().getLength()); // <=
    																										// =
    					Matcher matcher = p.matcher(out);
    					while (matcher.find()) {
    						textPane.getStyledDocument().setCharacterAttributes(matcher.start(), matcher.end() - matcher.start(), style_error, true);
    					}
    				} catch (BadLocationException ex) {
    					ex.printStackTrace();
    				}
    			}
    		});
    		buttons.add(style);
     
    		JFrame frame = new JFrame("Demo");
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		frame.getContentPane().add(panel);
    		frame.pack();
    		frame.setVisible(true);
     
    		// Robot :
    		// 1 : insert text
    		try {
    			textPane.getDocument().insertString(0, "this is a text\nDoo, a new line in this text\nA new line again !", null);
    		} catch (BadLocationException e1) {
    			// TODO Auto-generated catch block
    			e1.printStackTrace();
    		}
     
    		// 2 : Apply style :
    		style.getActionListeners()[0].actionPerformed(null);
     
    		// 3 : Undo
    		undoManager.undo();
     
    		// 4 : Insert new text
    		try {
    			textPane.getDocument().insertString(0, "1\n2", null);
    		} catch (BadLocationException e1) {
    			// TODO Auto-generated catch block
    			e1.printStackTrace();
    		}
     
    	}
    }
    Ce bug m'embête car j'aimerais corriger ce bogue lors de ma prochaine version ! ça fait 1 an qu'il dur ! :-(

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

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Par défaut
    En fait le JSyntaxPane a déjà un parser en interne, la seule chose à lui fournir serait un lexer décrivant le langage à colorer, il en propose déjà un certain nombre par défaut, il suffit de s'en inspirer pour en écrire un. Ensuite ton parser peut toujours être utilisé pour d'autres tâches (genre compilation & cie)

Discussions similaires

  1. Problème avec les classes et les méthodes abstract
    Par BOLARD dans le forum Langage
    Réponses: 5
    Dernier message: 22/09/2007, 20h27
  2. Problème avec une classe... "without object"
    Par z980x dans le forum C++
    Réponses: 8
    Dernier message: 27/04/2006, 16h00
  3. [PHPMailer] problème avec la classe phpmailer
    Par sansouna24 dans le forum Bibliothèques et frameworks
    Réponses: 1
    Dernier message: 08/04/2006, 16h51
  4. Problème avec la classe Calendar
    Par afrikha dans le forum Collection et Stream
    Réponses: 3
    Dernier message: 30/03/2006, 08h48
  5. Réponses: 9
    Dernier message: 25/09/2005, 16h33

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