7

I just faced an interesting thing.

I was changing selected text style. The thing is when I change style for ONE WORD one by one it's fine but next if I select a whole styled phrase and change its font color the whole phrase becomes ONE styled (the first style within the selected text) only :(

Here is the problem snippet

  private void setFontColorStyle()
    {
        JTextPane editor=this.getTextPane();
        String text=this.getTextPane().getSelectedText();

        StyledDocument doc=(StyledDocument) editor.getDocument();
        int selectionEnd=this.getTextPane().getSelectionEnd();
        int selectionStart=this.getTextPane().getSelectionStart();


        Element element=doc.getCharacterElement(selectionStart);
        AttributeSet as = element.getAttributes();

        String family = StyleConstants.getFontFamily(as);
        int fontSize = StyleConstants.getFontSize(as);
        boolean isBold=StyleConstants.isBold(as);
        boolean isItalic=StyleConstants.isItalic(as);
        boolean isUnderlined=StyleConstants.isUnderline(as);

        StyleContext context = new StyleContext();
        Style style;

        this.getTextPane().replaceSelection("");

        style = context.addStyle("mystyle", null);
        style.addAttribute(StyleConstants.FontSize, fontSize);
        style.addAttribute(StyleConstants.FontFamily, family);
        style.addAttribute(StyleConstants.Foreground, this.fontColor);
        style.addAttribute(StyleConstants.Bold, isBold);
        style.addAttribute(StyleConstants.Italic, isItalic);
        style.addAttribute(StyleConstants.Underline, isUnderlined);

        this.getTextPane().replaceSelection("");
        try {
            this.getTextPane().getStyledDocument().insertString(selectionEnd - text.length(), text, style);
        } catch (BadLocationException ex) {

        }
    }

And here is the bold making method code... () Italic and underlined all the same logic so I guess it is quite clear

private void setFontBoldStyle()
    {
         if(this.getTextPane().getSelectedText()!=null)
        {

        String text = this.getTextPane().getSelectedText();
        int selectionStart=this.getTextPane().getSelectionStart();
        int selectionEnd=this.getTextPane().getSelectionEnd();






        StyleContext context = new StyleContext();
        Style style;


        Element element=doc.getCharacterElement(selectionStart);
        Enumeration en=doc.getStyleNames();

        AttributeSet as = element.getAttributes();

        /**
         * Get style from history...
         */
        String family = StyleConstants.getFontFamily(as);
        int fontSize = StyleConstants.getFontSize(as);
        Color currentColor=StyleConstants.getForeground(as);
        boolean isBold=StyleConstants.isBold(as)?false:true;
        boolean isItalic=StyleConstants.isItalic(as);
        boolean isUnderlined=StyleConstants.isUnderline(as);

        String styleName=String.valueOf(Math.random());

        style = context.addStyle(styleName, null);
//        style.addAttribute(StyleConstants.FontSize, fontSize);
//        style.addAttribute(StyleConstants.FontFamily, family);
        style.addAttribute(StyleConstants.Foreground, currentColor);
        style.addAttribute(StyleConstants.FontFamily, family);
        style.addAttribute(StyleConstants.FontSize, fontSize);
        style.addAttribute(StyleConstants.Bold, isBold);
        style.addAttribute(StyleConstants.Italic, isItalic);
        style.addAttribute(StyleConstants.Underline, isUnderlined);

        this.getTextPane().replaceSelection("");



        try {
            this.getTextPane().getStyledDocument().insertString(selectionEnd - text.length(), text, style);
        } catch (BadLocationException ex) {

        }

        }//if end...


    }

Here is the bold method invokation code:

private void setFontBold()
    {
        this.setFontBoldStyle(); 
    }

... and color method invokation

 private void setFontColor(Color fontColor)
    {
        this.fontColor=fontColor;
        this.setFontColorStyle();

    }

... and action listeners (for bold)...

 private void boldButtonActionPerformed(java.awt.event.ActionEvent evt) {                                           
         this.getTextPane().requestFocusInWindow();
         this.setFontBold();
    }                                          

... and for color

private void colorButtonActionPerformed(java.awt.event.ActionEvent evt) {                                            

       this.getTextPane().requestFocusInWindow();

       ColorDialog colorEditor=new ColorDialog();

      //returns rgb color...
       Color color=colorEditor.getSelectedColor(this.getDialog(), true,false);


       if(color==null){
           JOptionPane.showMessageDialog(this.getDialog(), "null color");
           return;
       }

       this.setFontColor(color);
    }                                           

I dearly need your advice about how to keep selected text styles unchanged (like bold or font family) when I want to change a whole different styled selected text color for example?

To be more clear...

For example I have text

My Hello World is not pretty :)

Next I select the whole phrase and change its color from black to lets say red. Next text becomes red but the whole phrase becomes bold according to first style. But the thing is it would be interesting to keep bold and italic styles but at the same time have the phrase red :) So quite simple but I have just confused how to control more than one style in the frames of selected text area?

Any useful comment is much appreciated

user592704
  • 3,674
  • 11
  • 70
  • 107
  • 2
    Consider creating and posting an [SSCCE](http://sscce.org) to allow us to modify and test your code. – Hovercraft Full Of Eels Oct 02 '11 at 02:44
  • No idea! The question is good. +1 – Mohayemin Oct 02 '11 at 02:46
  • A bad solution may be adding new attribute character by character. – Mohayemin Oct 02 '11 at 02:47
  • Emm... That is the whole JButton actionPerformed method body. I have just edited the snippet watch it please – user592704 Oct 02 '11 at 03:20
  • @Mohaimin about the "bad solution"... and yes. I had the same thought first too :) But I really hope there should be some common decision for this kind of case? – user592704 Oct 02 '11 at 03:28
  • 2
    Again, an [SSCCE](http://sscce.org) would be better than either a snippet or the whole code. Please read the link. If you don't get a decent answer soon, you may consider creating and posting one of these as it will increase your chances of getting good help. – Hovercraft Full Of Eels Oct 02 '11 at 03:31
  • Nice snippet edits. Are you intending to (read the link and) post an SSCCE? – Andrew Thompson Oct 10 '11 at 02:24
  • The code describes just two actions A) making selected text bold B) change selected text color; To see how it works it just enough to make JTextPane and two JButtons (bold/color); The ColorDialog can be replaced with any static color as Color.BLUE for example :) It is a very simple code – user592704 Oct 10 '11 at 02:32

2 Answers2

3

TextComponentDemo, discussed in How to Use Editor Panes and Text Panes, is a good example of how to manage this as well as other text component features.

Addendum: TextComponentDemo relies on pre-defined Action objects to handle editing tasks. Conveniently, StyledEditorKit contains a series of nested classes that derive from StyledTextAction. As a concrete example, here's how one might add an AlignmentAction to the Style menu of TextComponentDemo in the method createStyleMenu():

protected JMenu createStyleMenu() {
    JMenu menu = new JMenu("Style");

    Action action = new StyledEditorKit.AlignmentAction(
        "left-justify", StyleConstants.ALIGN_LEFT);
    action.putValue(Action.NAME, "Left");
    menu.add(action);
    menu.addSeparator();
    ...
}

The remaining (arbitrary) alignment action names are defined privately in StyledEditorKit.

Addendum: setCharacterAttributes() is the common routine used by the nested editing actions. It invokes a method of the same name in StyledDocument, as proposed by @StanislavL.

Addendum: I am unable to reproduce the effect you describe. When I set the color of the selection, the style attributes remain unchanged.

Addendum: The StyledEditorKit actions work just as well with a JButton or JToolBar.

new JButton(new StyledEditorKit.ForegroundAction("Red", Color.red))

TextComponentDemo

trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • I've read the tutorial for many times but found no tips. If I have missed something point it to me please. – user592704 Oct 03 '11 at 17:15
  • I watched the snippet too. The thing is not in "MAKE A TEXT ALIGN LEFT" or something just once but how to keep the alignment if just to select all text and make it "green" for example. I watched many examples but none showed how to keep style history if it needed :( Maybe the thing is to change styled symbol by symbol in the frames of selected text but I am not sure how :( Actually that's why I asked the question. – user592704 Oct 03 '11 at 19:41
  • In the example, which uses the editor kit's actions, changing any attribute leaves the remaining attributes unchanged. Why not use them? – trashgod Oct 03 '11 at 19:50
  • Emm because the thing is not to change a word by word totally but select a whole phrase (n words length) and set it let say green but keep its bold or italic styles at the same time. – user592704 Oct 06 '11 at 02:12
  • IIUC, this is exactly how the actions in the example behave. – trashgod Oct 06 '11 at 02:16
  • My current JTextPane works not like that I mean as an example: I have word A, word B, word C; word A (bold), word B (default), word C (italic); I select AS ONE PHRASE word A, word B, word C; next I set font color attribute as "green"; result: word A, word B, word C become green BUT now the whole phrase as (word A)+(word B)+(word C ) is (bold) – user592704 Oct 06 '11 at 02:17
  • Is it a style sharing effect or I don't get it :S – user592704 Oct 06 '11 at 02:18
  • I'd like to use JMenu but It's all because I want not to use JMenu object for actions but JButton :( So, of course, I had to put all text modification code into its actionPerformed method but it makes problem as I can see :( Could you show the color changing code? – user592704 Oct 07 '11 at 16:05
  • I've added a button example above. Please edit your question to include an [sscce](http://sscce.org/) that exhibits the problem. – trashgod Oct 07 '11 at 16:33
  • Thank you :) It is quite interesting snippet. But I tried to use JColorChooser to get dynamic color every time :S Is it OK or just static colors can be supported? – user592704 Oct 07 '11 at 19:09
  • I'd create an editable palette of colors with an action for each. I don't see your update. – trashgod Oct 07 '11 at 19:55
  • I thought that, too, but I want to use a dynamic color palette that's why I search another way with Element object. I am not sure but still maybe there is a way to change a character by character with a loop. How you think? :S – user592704 Oct 09 '11 at 04:35
  • The actions modify the selection, whether it's one character or many. – trashgod Oct 09 '11 at 04:44
  • See [`setCharacterAttributes()`](http://www.java2s.com/Open-Source/Java-Document/6.0-JDK-Core/swing/javax/swing/text/StyledEditorKit.java.htm). – trashgod Oct 10 '11 at 02:51
  • Thank you but I am not pretty sure how to use this method in my case :S Could you show some demo snippets? – user592704 Oct 10 '11 at 16:28
  • I can't to better that the author, Timothy Prinzing. – trashgod Oct 10 '11 at 16:31
3

Use this.getTextPane().getStyledDocument().setCharacterAttributes()

StanislavL
  • 56,971
  • 9
  • 68
  • 98