【问题标题】:How can I set each character to a different color/background color in a JTextPane?如何在 JTextPane 中将每个字符设置为不同的颜色/背景颜色?
【发布时间】:2012-10-15 23:33:11
【问题描述】:

我一直在寻找这个,到目前为止,我所能想到的只是如何创建一种样式并将其应用于这样的角色:

StyledDocument doc = (StyledDocument) new DefaultStyledDocument();
JTextPane textpane = new JTextPane(doc);
textpane.setText("Test");
javax.swing.text.Style style = textpane.addStyle("Red", null);
StyleConstants.setForeground(style, Color.RED);
doc.setCharacterAttributes(0, 1, textpane.getStyle("Red"), true); 

如果您的文档中只有几个样式并希望按名称存储它们以便以后轻松应用它们,这将非常有用。在我的应用程序中,我希望能够为文本中的每个字符独立设置前景色(少数几个值之一)和背景色(灰度,许多不同的值)。为此创造可能成百上千的不同风格似乎是一种巨大的浪费。有没有办法设置这些属性而不必每次都创建新样式?如果我只需要渲染文本会容易得多,但我还需要使其可编辑。有没有办法用JTextPane 做到这一点,或者是否有另一个提供此功能的摇摆类?

【问题讨论】:

    标签: java swing jtextpane jtextcomponent styleddocument


    【解决方案1】:

    我不确定你的意思,但你不能循环遍历JtextPane 中的每个字符,并在该循环中遍历你想要突出显示的所有字母/字符等。有一个 if语句检查字符,然后相应地设置Style

    这是我做的一个例子,我只为字符 hw 实现了它,用于演示目的:

    //necessary imports
    import java.awt.Color;
    import java.util.ArrayList;
    import javax.swing.JFrame;
    import javax.swing.JTextPane;
    import javax.swing.text.DefaultStyledDocument;
    import javax.swing.text.StyleConstants;
    import javax.swing.text.StyledDocument;
    
    public class Test {
    
        /**
         * Default constructor for Test.class
         */
        public Test() {
            initComponents();
        }
    
        public static void main(String[] args) {
    
            /**
             * Create GUI and components on Event-Dispatch-Thread
             */
            javax.swing.SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    Test test = new Test();
                }
            });
        }
    
        /**
         * Initialize GUI and components (including ActionListeners etc)
         */
        private void initComponents() {
            JFrame jFrame = new JFrame();
            jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            StyledDocument doc = (StyledDocument) new DefaultStyledDocument();
            JTextPane textPane = new JTextPane(doc);
            textPane.setText("Hello, world! :)");
    
            //create necessary styles for various characters
            javax.swing.text.Style style = textPane.addStyle("Red", null);
            StyleConstants.setForeground(style, Color.RED);
            javax.swing.text.Style style2 = textPane.addStyle("Blue", null);
            StyleConstants.setForeground(style2, Color.BLUE);
    
            //create array of characters to check for and style
            String[] lettersToEdit = new String[]{"h", "w"};
    
            //create arraylist to hold each character in textPane
            ArrayList<String> strings = new ArrayList<>();
    
            //get all text
            String text = textPane.getText();
    
            //populate arraylist
            for (int i = 0; i < text.length(); i++) {
                strings.add(text.charAt(i) + "");
            }
    
            //declare variabe to hold position
            int position = 0;
    
            for (String s1 : strings) {//for each character in the textpane text
                for (String s2 : lettersToEdit) {//for each character in array to check (lettersToEdit)
                    if (s2.toLowerCase().equalsIgnoreCase(s1)) {//if there was a match
    
                        System.out.println("found a match: " + s1);
                        System.out.println("counter: " + position + "/" + (position + 1));
    
                        //check which chacacter we matched
                        if (s1.equalsIgnoreCase(lettersToEdit[0])) {
                            //set appropriate style
                            doc.setCharacterAttributes(position, 1, textPane.getStyle("Red"), true);
                        }
                        if (s1.equalsIgnoreCase(lettersToEdit[1])) {
                            doc.setCharacterAttributes(position, 1, textPane.getStyle("Blue"), true);
                        }
                    }
                }
                //increase position after each character on textPane is parsed
                position++;
            }
    
            jFrame.add(textPane);
            //pack frame (size JFrame to match preferred sizes of added components and set visible
            jFrame.pack();
            jFrame.setVisible(true);
        }
    }
    

    【讨论】:

    • 谢谢大卫。单独设置每个角色并不是什么大问题,只是每个角色都需要一种可能不会与任何其他角色共享的新风格。我需要为数千个字符执行此操作,因此可能需要数百种样式。我只想这样做,而不必每次都添加新的命名样式。虽然只有几种前景色中的一种,所以我想我可以将文本放在我自己渲染的背景上。
    【解决方案2】:

    如果您想更改文本窗格中每个字符的样式,这里有一个完全随机的方法。您为每个角色创建不同的属性集。由您来找到合适的组合(前景/背景对比,字符大小没有太大差异等......)。您还可以存储已应用的不同样式,这样您就不会重复使用相同的样式。

    import java.awt.Color;
    import java.util.Random;
    
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    import javax.swing.JTextPane;
    import javax.swing.text.DefaultStyledDocument;
    import javax.swing.text.SimpleAttributeSet;
    import javax.swing.text.StyleConstants;
    import javax.swing.text.StyledDocument;
    
    public class TestDifferentStyles {
        private void initUI() {
            JFrame frame = new JFrame(TestDifferentStyles.class.getSimpleName());
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            StyledDocument doc = new DefaultStyledDocument();
            JTextPane textPane = new JTextPane(doc);
            textPane.setText("Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has "
                    + "been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of "
                    + "type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the "
                    + "leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the"
                    + " release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing "
                    + "software like Aldus PageMaker including versions of Lorem Ipsum.");
    
            Random random = new Random();
            for (int i = 0; i < textPane.getDocument().getLength(); i++) {
                SimpleAttributeSet set = new SimpleAttributeSet();
                // StyleConstants.setBackground(set, new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256)));
                StyleConstants.setForeground(set, new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256)));
                StyleConstants.setFontSize(set, random.nextInt(12) + 12);
                StyleConstants.setBold(set, random.nextBoolean());
                StyleConstants.setItalic(set, random.nextBoolean());
                StyleConstants.setUnderline(set, random.nextBoolean());
    
                doc.setCharacterAttributes(i, 1, set, true);
            }
    
            frame.add(new JScrollPane(textPane));
            frame.setSize(500, 400);
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
    
            javax.swing.SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    new TestDifferentStyles().initUI();
                }
            });
        }
    
    }
    

    【讨论】:

    • 文字有版权问题吗?很想在 SwingX 测试工具中使用它:-)
    • @kleopatra AFAIK "Lorem ipsum" 已存在 500 多年,因此属于公共领域。
    【解决方案3】:

    我认为最好的方法是像我们在具有突出显示的编辑器中那样,不是追逐字符,而是有一个模式,例如:

    private static HashMap<Pattern, Color> patternColors;
    private static String GENERIC_XML_NAME = "[A-Za-z]+[A-Za-z0-9\\-_]*(:[A-Za-z]+[A-Za-z0-9\\-_]+)?";
    private static String TAG_PATTERN = "(</?" + GENERIC_XML_NAME + ")";
    private static String TAG_END_PATTERN = "(>|/>)";
    private static String TAG_ATTRIBUTE_PATTERN = "(" + GENERIC_XML_NAME + ")\\w*\\=";
    private static String TAG_ATTRIBUTE_VALUE = "\\w*\\=\\w*(\"[^\"]*\")";
    private static String TAG_COMMENT = "(<\\!--[\\w ]*-->)";
    private static String TAG_CDATA = "(<\\!\\[CDATA\\[.*\\]\\]>)";
    
    private static final Color COLOR_OCEAN_GREEN = new Color(63, 127, 127);
    private static final Color COLOR_WEB_BLUE = new Color(0, 166, 255);
    private static final Color COLOR_PINK = new Color(127, 0, 127);
    
    static {
        // NOTE: the order is important!
        patternColors = new LinkedHashMap<Pattern, Color>();
        patternColors.put(Pattern.compile(TAG_PATTERN), Color.BLUE); // COLOR_OCEAN_GREEN | Color.BLUE
        patternColors.put(Pattern.compile(TAG_CDATA), COLOR_WEB_BLUE);
        patternColors.put(Pattern.compile(TAG_ATTRIBUTE_PATTERN), COLOR_PINK);
        patternColors.put(Pattern.compile(TAG_END_PATTERN), COLOR_OCEAN_GREEN);
        patternColors.put(Pattern.compile(TAG_COMMENT), Color.GRAY);
        patternColors.put(Pattern.compile(TAG_ATTRIBUTE_VALUE), COLOR_OCEAN_GREEN); //Color.BLUE | COLOR_OCEAN_GREEN
    }
    
    
    
    
    public XmlView(Element element) {
    
        super(element);
    
        // Set tabsize to 4 (instead of the default 8).
        getDocument().putProperty(PlainDocument.tabSizeAttribute, 4);
    }
    

    【讨论】:

      猜你喜欢
      • 2013-10-26
      • 2016-02-28
      • 2018-02-26
      • 2020-12-14
      • 1970-01-01
      • 1970-01-01
      • 2020-05-08
      • 2019-02-28
      • 1970-01-01
      相关资源
      最近更新 更多