4 Replies Latest reply on Sep 27, 2005 1:17 PM by 843805

    Replacing text in JTextPane with an image (think smileys)

    843805
      Hey,

      I've been working on a chat program. I'm trying to implement smileys currently. Here's the issue.

      The main chat is being displayed in a JTextPane. I know how to add styled text and images using StyledDocument but I need something more and I THINK it has something to do with DocumentFilter. It's very simple really, I just want certain text in this chat area to be replaced by a picture. For example, all instances of ":)" in the chat area should be replaced by an image of a smiley.

      Thanks in advance,

      Arzin
        • 1. Help?
          843805
          Any ideas guys? It's kinda urgent.
          • 2. Re: Help?
            843805
            Try this.

            regards,
            Stas
            import java.awt.*;
            import java.awt.image.*;
            import javax.swing.*;
            import javax.swing.event.*;
            import javax.swing.text.*;
            
            public class Test1
                extends JFrame {
                //autoreplacing :) with picture
                JTextPane p = new JTextPane();
                public Test1() throws Exception {
                    p.setEditorKit(new StyledEditorKit());
                    getContentPane().add(p, BorderLayout.CENTER);
                    SimpleAttributeSet attrs = new SimpleAttributeSet();
                    StyleConstants.setIcon(attrs, getImage());
                    p.addCaretListener(new CaretListener() {
                        public void caretUpdate(CaretEvent e) {
                            SwingUtilities.invokeLater(new Runnable() {
                                public void run() {
                                    try {
                                        StyledDocument doc = (StyledDocument) p.getDocument();
                                        String text = doc.getText(0, p.getDocument().getLength());
                                        int index = text.indexOf(":)");
                                        int start = 0;
                                        while (index > -1) {
                                            Element el = doc.getCharacterElement(index);
                                            if (StyleConstants.getIcon(el.getAttributes()) == null) {
                                                doc.remove(index, 2);
                                                SimpleAttributeSet attrs = new SimpleAttributeSet();
                                                StyleConstants.setIcon(attrs, getImage());
                                                doc.insertString(index, ":)", attrs);
                                            }
                                            start = index + 2;
                                            index = text.indexOf(":)", start);
                                        }
                                    }
                                    catch (Exception ex) {
                                        ex.printStackTrace();
                                    }
                                }
                            });
                        }
                    });
                    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    this.setSize(400, 400);
                }
            
                public static void main(String[] args) throws Exception {
                    Test1 test11 = new Test1();
                    test11.show();
                }
            
                protected ImageIcon getImage() {
                    BufferedImage bi = new BufferedImage(15, 15, BufferedImage.TYPE_INT_ARGB);
                    Graphics g = bi.getGraphics();
                    g.setColor(Color.red);
                    g.drawOval(0, 0, 14, 14);
                    g.drawLine(4, 9, 9, 9);
                    g.drawOval(4, 4, 1, 1);
                    g.drawOval(10, 4, 1, 1);
                    return new ImageIcon(bi);
                }
            }
            • 3. Re: Help?
              843805
              Thanks a bunch StanislavL. Your code really helped.

              I had encountered a few issues while using your logic for multiple smileys. But now I got it to work. However, it doesn't work perfectly. In the sense, for certain strings, it throws BadLocationException but the replacement is done correctly. It's weird. I think it has something to do with the remove function. Check it out, see if you can fix the problem.
              class smileyThread implements Runnable
                   {
                        public void run()
                        {
                             try
                             {
                                  StyledDocument doc2=chc.tachatarea.getStyledDocument();
                                  String text=doc2.getText(0,doc2.getLength());
                                  SimpleAttributeSet smi;
                                  int index;
                                  int start=0;
                                  char c;
                                  index=text.indexOf(':');
                                  while(index>-1)
                                  {
                                       synchronized(this){
                                       Element e1=doc2.getCharacterElement(index);
                                       if (StyleConstants.getIcon(e1.getAttributes()) == null)
                                       {
                                            if(index<text.length())c=text.charAt(index+1);
                                            else break;
                                            switch(c)
                                            {
                                                 case ')':
                                                 doc2.remove(index,2);
                                                 smi=new SimpleAttributeSet();
                                                 StyleConstants.setIcon(smi,new ImageIcon("images\\smileys\\happy.gif"));
                                                 doc2.insertString(index,":)",smi);
                                                 start=(index+2);
                                                 break;
                                                 
                                                 case '(':
                                                 doc2.remove(index,2);
                                                 smi=new SimpleAttributeSet();
                                                 StyleConstants.setIcon(smi,new ImageIcon("images\\smileys\\sad.gif"));
                                                 doc2.insertString(index,":(",smi);
                                                 start=(index+2);
                                                 break;
                                                 
                                                 case '@':
                                                 doc2.remove(index,2);
                                                 smi=new SimpleAttributeSet();
                                                 StyleConstants.setIcon(smi,new ImageIcon("images\\smileys\\angry.gif"));
                                                 doc2.insertString(index,":@",smi);
                                                 start=(index+2);
                                                 break;
                                                 default:
                                                 start=(index+1);
                                            }     
                                       }     
                                       else start=(index+1);
                                       index=(text.indexOf(':',start));}
                                  }
                                  chc.tachatarea.setStyledDocument(doc2);     
                             }
                             catch(BadLocationException exc)
                             {
                                  System.out.println("Bad Location");
                                  exc.printStackTrace();
                             }
                        }
                   }
              • 4. Re: Help?
                843805
                Any ideas Stans (or anyone else)?

                It's working for multiple smileys (emoticons) but If I spam too many smileys in a line (more than width of the pane I think) using the logic in smileyThread (given in above post), the BadLocationException exception is thrown. I think it's because of the way JTextPane handles word wrapping. It says Invalid Removal in the stack trace when this exception occurs, but the smiley replacement is done correctly 90% of the time even when the exception is thrown (needless to say, when the exception is not thrown, it works perfect). Help!

                Thanks,

                Arzin