如何在使用HTMLEditorKit构建的HTML编辑器中提供用于更改文本部件背景颜色的功能 [英] How to provide Functionalty for Changing the Background Color of Text Parts in HTML Editor built with HTMLEditorKit

查看:112
本文介绍了如何在使用HTMLEditorKit构建的HTML编辑器中提供用于更改文本部件背景颜色的功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题如下:

我想让我的小HTML编辑器的用户能够在 输入的文本使用不同的背景色.我第一次尝试 为此使用CSS样式.不同的风格定义 不同的背景色,并且通过JComboBox用户可以 在这些样式之间切换.在选择样式后 HTMLDocument内各自的位置,类型为新的HTML元素 将输入<span class="style">. 不幸的是,我无法完成这项工作.跨度元素 根本就没有创建(请参阅我关于此问题的问题).

I want to enable the user of my little HTML editor to switch between different background colors for the text being entered. I first tried to use CSS styles for that purpose. The different styles define different background colors and through a JComboBox the user could switch between these styles. Upon selection of a style in the respective position inside the HTMLDocument a new HTML element of type <span class="style"> would be entered. Unfortunately I could not manage to get this work. The span elements were simply not created (see my question regarding this problem).

之间,我看了课StyledEditorKit.ForegroundAction 了解其功能.执行后,只需修改 StyledEditorKit的输入属性在使用中设置新 前景色.随后输入的文本显示为 新的前景色.当将HTML代码写入文件时, 文本自动包含在<font color=".."> ... </font>中 HTML元素.所有这些甚至都适用于选定的文本,这可能会 遍历多个段落.在这种情况下,显然受影响 所有受影响的段落中的文本都包含在<font ...> HTML标记中.

In between I took a look at the class StyledEditorKit.ForegroundAction to learn how this functions. Upon execution it simply modifies the input attributes of the StyledEditorKit in use setting a new foreground color. Text that is entered afterwards is displayed with the new foreground color. And when writing the HTML code into a file, the text is automagically enclosed in <font color=".."> ... </font> HTML elements. And all that even works on selected text which might run over multiple paragraphs. In this case obviously the affected text inside all affected paragraphs is enclosed into <font ...> HTML tags.

我想完成设置背景的相同功能 任意文本上的颜色.但令人惊讶的是,这似乎没有 如此简单:-(

I want to accomplish the same functionality for setting the background color on arbitrary chunks of text. But surprisingly this does not seem to be so easy:-(

我没有为此目的找到预定义的动作类,类似于 Java 7 JDK中的StyledEditorKit.foregroundAction.创造 这样的课程似乎并不复杂;它几乎与 ForegroundActionactionPerformed方法更改为设置 背景,而不是前景属性.

I didn't find a predefined action class for that purpose similar to the StyledEditorKit.foregroundAction in the Java 7 JDK. Creating such a class does not seem to be complex; it's almost the same as the ForegroundAction with the actionPerformed method changed to set the background instead of the foreground attribute.

但是如何创建设置特定背景的有效HTML代码 所包含文本的部分颜色是多少? 到目前为止,我不知道HTMLEditorKit的哪一部分执行 为HTMLDocument中的文本创建所有<font>元素 设置了前台属性.我认为从现有的代码 创建<font>元素,派生一个 创建<span style="background-color:...">的实现 元素而不是<font>元素来设置背景色 用于文本的任意区域.还是所有这些都可用,我 只是没有注意到?任何帮助将不胜感激!

But how to create valid HTML code that sets a specific background color for parts of the contained text? Until now I don't know which part of the HTMLEditorKit performs the creation of all the <font> elements for text in the HTMLDocument that has the foreground attribute set. I think from the existing code creating the <font> elements it should not be too hard to derive an implementation that creates <span style="background-color:..."> elements instead of <font> elements for setting the background color for arbitrary regions of text. Or is all this already available and I only didn't notice? Any help would be appreciated!

在此之间,我迈出了重要的一步,这要感谢找到的一段代码

In between I made a significant step forward and thanks to a piece of code found here I managed to create valid <span> elements. In the span elements I use the class attribute to assign a predefined style.

这是我的代码:

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Vector;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JTextPane;
import javax.swing.JToolBar;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.Style;
import javax.swing.text.StyleContext;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.StyleSheet;

public class SimpleEditor extends JFrame {

    private static final long   serialVersionUID = 1L;
    private final JTextPane   textPane;
    private final HTMLEditorKit edtKit;
    private final HTMLDocument  doc;
    private final StyleSheet predefStyles;

    public static void main(String[] args) throws BadLocationException, IOException {
        final SimpleEditor editor = new SimpleEditor();
        editor.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        editor.setVisible(true);
    }

    public SimpleEditor() throws BadLocationException, IOException {
        super("Very Simple HTML Editor");
        textPane = new JTextPane();
        edtKit = new HTMLEditorKit();
        textPane.setEditorKit(edtKit);
        predefStyles = new StyleSheet();
        predefStyles.addRule(".MyStyle1 { color:#cc0000; background-color:silver }\n" +
                             ".MyStyle2 { color:#0000cc; background-color:aqua }");
        doc = new HTMLDocument(predefStyles);
        textPane.setDocument(doc);

        final Container content = getContentPane();
        content.add(textPane, BorderLayout.CENTER);
        content.add(createToolBar(), BorderLayout.NORTH);
        setJMenuBar(createMenuBar());
        setSize(500, 240);
    }

    private JToolBar createToolBar() {
        final Vector<String> styleNames = new Vector<String>();
        final Enumeration<?> names = predefStyles.getStyleNames();
        while (names.hasMoreElements()) {
            styleNames.add((String) names.nextElement());
        }
        final DefaultComboBoxModel<String> stylesModel =
                new DefaultComboBoxModel<String>(styleNames);
        final JComboBox<String> cbStyleSel = new JComboBox<String>(stylesModel);
        final JToolBar bar = new JToolBar();
        Action dumpAction = null;
        for (final Action act : edtKit.getActions()) {
            if (act.getValue(Action.NAME).equals("dump-model")) {
                dumpAction = act;
                break;
            }
        }
        bar.add(dumpAction);
        cbStyleSel.setEditable(false);
        cbStyleSel.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                e.getSource();
                @SuppressWarnings("unchecked")
                final JComboBox<CondStyle> cboStyleSel = (JComboBox<CondStyle>) e.getSource();
                final String selItem = (String) cboStyleSel.getSelectedItem();
                final MutableAttributeSet divAttributes = new SimpleAttributeSet();
                if (selItem.equals("default")) {
                    // This does not work!
                    final Style defStyle = StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE);
                    divAttributes.addAttribute(HTML.Tag.CONTENT, defStyle);
                    textPane.setCharacterAttributes(divAttributes, true);
                } else {
                    divAttributes.addAttribute(HTML.Attribute.CLASS, selItem.substring(1));
                    final MutableAttributeSet tagAttributes = new SimpleAttributeSet();
                    tagAttributes.addAttribute(HTML.Tag.SPAN, divAttributes);
                    textPane.setCharacterAttributes(tagAttributes, false);
                }
                textPane.requestFocusInWindow();
            }
        });
        bar.add(cbStyleSel);
        return bar;
    }

    /**
     * Extracts the style attributes except the style's name
     * @param aStyle The style to be processed
     * @return The visual attributes extracted from the style
     */
    AttributeSet extractStyleAttribs(Style aStyle) {
        final MutableAttributeSet attribs = new SimpleAttributeSet();
        final Enumeration<?> attribNames = aStyle.getAttributeNames();
        while (attribNames.hasMoreElements()) {
            final Object attribName = attribNames.nextElement();
            if (attribName == Style.NameAttribute) {
                continue;
            }
            attribs.addAttribute(attribName, aStyle.getAttribute(attribName));
        }
        return attribs;
    }

    private JMenuBar createMenuBar() {
        final JMenuBar menubar = new JMenuBar();
        final JMenu mnuFile = new JMenu("File");
        menubar.add(mnuFile);
        final SaveAction actSave = new SaveAction();
        mnuFile.add(actSave);
        return menubar;
    }

    class SaveAction extends AbstractAction {
        private static final long serialVersionUID = 1L;
        public SaveAction() {
            super("Save");
        }
        @Override
        public void actionPerformed(ActionEvent ev) {
            final JFileChooser chooser = new JFileChooser();
            if (chooser.showSaveDialog(SimpleEditor.this) != JFileChooser.APPROVE_OPTION)
                return;
            final File file = chooser.getSelectedFile();
            if (file == null)
                return;
            FileWriter writer = null;
            try {
                writer = new FileWriter(file);
                textPane.write(writer);
            } catch (final IOException ex) {
                JOptionPane.showMessageDialog(SimpleEditor.this,
                                              "File Not Saved", "ERROR",
                                              JOptionPane.ERROR_MESSAGE);
            } finally {
                if (writer != null) {
                    try {
                        writer.close();
                    } catch (final IOException x) {
                    }
                }
            }
        }
    }
}

到目前为止一切顺利!我对这种解决方案的唯一问题是,我无法实现将<span>元素中包含的文本切换回普通"文本的操作.文字,即未放置在<span>元素内的文字. 这应该没什么大不了的,但是不幸的是我无法弄清楚如何才能做到这一点.任何想法都将非常受欢迎!

So far so good! My only problem with this solution is that I couldn't manage to implement the switch back from text enclosed in <span> elements to "normal" text, i.e. text that is not placed inside of <span> elements. This should be no big deal but unfortunately I couldn't figure out how I can accomplish that. Any ideas would be very welcome!

推荐答案

我明白了!而且非常简单;-) 要使用<span>元素从样式化的文本条目中退回,我只需要从当前文本的输入属性中删除HTML.Tag.SPAN属性.这是通过以下步骤完成的:

I got it! And it's sooo simple;-) To switch back from the styled text entry using <span> elements I only had to remove the HTML.Tag.SPAN attribute from the input attributes of the current text. This is accomplished as follows:

edtKit.getInputAttributes().removeAttribute(HTML.Tag.SPAN);

因此,我在(已更新的)问题中发布的示例代码中的ActionListener代码现在看起来如下:

So the code for the ActionListener in the example code I posted in my (updated) question now looks as follows:

        cbStyleSel.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            e.getSource();
            @SuppressWarnings("unchecked")
            final JComboBox<CondStyle> cboStyleSel = (JComboBox<CondStyle>) e.getSource();
            final String selItem = (String) cboStyleSel.getSelectedItem();
            if (selItem.equals("default")) {
                edtKit.getInputAttributes().removeAttribute(HTML.Tag.SPAN);
            } else {
                final MutableAttributeSet divAttributes = new SimpleAttributeSet();
                divAttributes.addAttribute(HTML.Attribute.CLASS, selItem.substring(1));
                final MutableAttributeSet tagAttributes = new SimpleAttributeSet();
                tagAttributes.addAttribute(HTML.Tag.SPAN, divAttributes);
                textPane.setCharacterAttributes(tagAttributes, false);
            }
            textPane.requestFocusInWindow();
        }
    });

关于实现该功能的问题,我发布了多个问题(请参见此处

I had posted multiple questions regarding my problems implementing that functionality (see here, and here) but got no answers. Maybe the issue was too trivial;-)

这篇关于如何在使用HTMLEditorKit构建的HTML编辑器中提供用于更改文本部件背景颜色的功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆