在写作时更改JTextPane中的样式

时间:2012-09-23 23:30:39

标签: java swing styles jtextpane

我创建了一个具有两种不同样式的jtextpane:一个用于数字(粉红色前景),另一个用于默认样式(黑色前景)。我在jtextpane上添加了一个keylistener(我使用KeyReleased函数)来处理新的按下字符,但是我在写作时遇到了问题。方案如下:

  • 文字是:hello 123
  • 'hello'文字为黑色,数字'123'为粉红色。
  • 现在插入符号位于'1'和'2'之间,我按'a'并发生一些奇怪的事情。
  • 字符'a'变为粉红色,然后变成黑色。

为什么它会在短时间内变黑?

我以这种方式处理KeyReleased:

  1. 我使用默认样式(清洁阶段)
  2. 设置所有文本
  3. 我将仅为数字
  4. 更改粉红色的前景

    这是一个例子:

    import java.awt.Color;
    import java.awt.event.KeyAdapter;
    import java.awt.event.KeyEvent;
    import java.util.StringTokenizer;
    
    import javax.swing.JFrame;
    import javax.swing.JTextPane;
    import javax.swing.text.Style;
    import javax.swing.text.StyleConstants;
    
    
    public class Example extends JFrame {
    
    JTextPane pn = new JTextPane();
    public Example() {
    
        addDefaultStyle(pn);
        addNumberStyle(pn);
    
        pn.addKeyListener(new KeyAdapter() {
    
            @Override
            public void keyReleased(KeyEvent arg0) {
                String text = pn.getText();
    
    
                pn.getStyledDocument().setCharacterAttributes(0, text.length(), pn.getStyle("default"), true);
    
                StringTokenizer ts = new StringTokenizer(text, " ");
    
                while(ts.hasMoreTokens()){
                    String token = ts.nextToken();
    
                    try{
                        Integer.parseInt(token);
    
                        pn.getStyledDocument().setCharacterAttributes(text.indexOf(token), token.length(), pn.getStyle("numbers"), true);
    
                    }catch(Exception e){
    
                        pn.getStyledDocument().setCharacterAttributes(text.indexOf(token), token.length(), pn.getStyle("default"), true);
                    }
                }
    
            }
        });
    
        getContentPane().add(pn);
        setSize(400, 400);
        setLocationRelativeTo(null);
        setVisible(true);
    }
    
    private void addDefaultStyle(JTextPane pn){
        Style style = pn.addStyle("default", null);
    
        pn.setForeground(Color.blue);
        pn.setBackground(Color.WHITE);
    
        StyleConstants.setForeground(style, pn.getForeground());
        StyleConstants.setBackground(style, pn.getBackground());
        StyleConstants.setBold(style, false);
    }
    
    private void addNumberStyle(JTextPane pn){
        Style style = pn.addStyle("numbers", null);
    
        StyleConstants.setForeground(style, Color.PINK);
        StyleConstants.setBackground(style, Color.WHITE);
        StyleConstants.setBold(style, true);
    }
    
    public static void main(String args []){
        new Example();
    }
    }
    

3 个答案:

答案 0 :(得分:1)

答案 1 :(得分:0)

  1. 为什么会变黑?
    • 应该。 1a2不是有效的整数。它会在短时间内变为粉红色bcos,您的格式化仅在事件发生后发生。当您在粉红色字符之间书写时,您的文本将为粉红色(直到您更改它)。
  2. 其他要点:

    • 由于您只需要格式化数字,因此无需将“默认”样式应用于已经是“默认”的其他字符。
    • 在我的解决方案中,我按数字去了。如果你想要整数(“1a2”将为假),那么继续使用StringTokenizer。只要知道如果句子末尾有一个数字,就不会匹配 - I am 12.

    代码:

    public void keyReleased(KeyEvent arg0) {
        applyStyle();
    }
    
    public void applyStyle() {
        String text = pn.getText();
        pn.getStyledDocument().setCharacterAttributes(0, text.length(), pn.getStyle("default"), true);
    
        char[] textChar = text.toCharArray();
        for(int i=0, len=textChar.length; i<len; i++){
            if(Character.isDigit(textChar[i]))
                pn.getStyledDocument().setCharacterAttributes(i, 1, pn.getStyle("numbers"), true);
        }
    }
    

    或者,我会使用DocumentListener代替KeyListener

    public class SmartTextPane extends JTextPane implements DocumentListener{
    
        public SmartTextPane(){ 
            super();
            this.getDocument().addDocumentListener(this);
        }
    
        public void changedUpdate(DocumentEvent e){ 
            applyStyle();
        }
        public void insertUpdate(DocumentEvent e){} 
        public void removeUpdate(DocumentEvent e){}
    
        //define your style functions
    }
    

答案 2 :(得分:0)

我有几乎相同的问题,我突然强调并做了类似的事情 inputTextDocModel.setCharacterAttributes(0, inputTextDocModel.getLength() + 1, styleNormal, true);将突出显示的字符切换为正常。但是这个 实际上将申请现有的字符,但不适用于插入符的属性。所以新角色仍然出现并突出显示了#39;虽然我已经将所有内容设置为正常&#39;

我做了类似跟随的事情,它覆盖了DocumentFilter中的replace()

public void replace(DocumentFilter.FilterBypass fb, int offset, int length, String text, AttributeSet attrs)
            throws BadLocationException {
 // styleNormal is the 'normal' Style, styleMarked is the 'highlighting' style

     inputTextDocModel.setCharacterAttributes(0, inputTextDocModel.getLength() + 1, styleNormal, true);
     super.replace(fb, offset, length, text, styleNormal.copyAttributes());

  // this is to make sure the caret update its style from 'highlighter' to 'normal' - 
  // assume variable 'editorkit' assigned as StyledEditorKit and has been assigned to the component 
  // by textcomponent.setEditorKit(editorkit)

     editorkit.getInputAttributes().removeAttributes(styleMarked.getAttributeNames());
}

我希望这个&#39;解决方案&#39;帮助

更新:实际上我们可以简单地使用StyledEditorKit来检索和修改插入符号属性并删除突出显示属性。 所以我更新了上面的代码,实现了正确的解决方案。