Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JTextPane - a phrase with TWO styles

Tags:

java

swing

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

like image 556
user592704 Avatar asked Oct 02 '11 02:10

user592704


1 Answers

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

like image 143
trashgod Avatar answered Sep 28 '22 05:09

trashgod