JTextPane - a phrase with TWO styles
Asked Answered
F

2

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

Featherstone answered 2/10, 2011 at 2:29 Comment(8)
Consider creating and posting an SSCCE to allow us to modify and test your code.Giantism
No idea! The question is good. +1Gastric
A bad solution may be adding new attribute character by character.Gastric
Emm... That is the whole JButton actionPerformed method body. I have just edited the snippet watch it pleaseFeatherstone
@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?Featherstone
Again, an SSCCE 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.Giantism
Nice snippet edits. Are you intending to (read the link and) post an SSCCE?Camporee
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 codeFeatherstone
S
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

Supervisory answered 2/10, 2011 at 6:19 Comment(16)
I've read the tutorial for many times but found no tips. If I have missed something point it to me please.Featherstone
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.Featherstone
In the example, which uses the editor kit's actions, changing any attribute leaves the remaining attributes unchanged. Why not use them?Supervisory
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.Featherstone
IIUC, this is exactly how the actions in the example behave.Supervisory
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)Featherstone
Is it a style sharing effect or I don't get it :SFeatherstone
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?Featherstone
I've added a button example above. Please edit your question to include an sscce that exhibits the problem.Supervisory
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?Featherstone
I'd create an editable palette of colors with an action for each. I don't see your update.Supervisory
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? :SFeatherstone
The actions modify the selection, whether it's one character or many.Supervisory
See setCharacterAttributes().Supervisory
Thank you but I am not pretty sure how to use this method in my case :S Could you show some demo snippets?Featherstone
I can't to better that the author, Timothy Prinzing.Supervisory
E
3

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

Expansion answered 2/10, 2011 at 11:34 Comment(2)
You mean to get a character by character ?Featherstone
You mean get ONE character by ONE style? But how then?Featherstone

© 2022 - 2024 — McMap. All rights reserved.