简体   繁体   English

无法从JTextPane中正确保存样式文本

[英]Styled Text not properly saved from JTextPane

I'm trying to implement a little HTML editor that allows for application of foreground and background colors to parts of the text. 我正在尝试实现一个小的HTML编辑器,该编辑器允许将前景色和背景色应用到部分文本中。 I want to store the text in HTML format with the coloring information kept in the file. 我想以HTML格式存储文本,并将着色信息保留在文件中。 My current implementation functions properly when editing text in it using different styles (the styles define foreground and background color information). 当使用不同的样式(其中的样式定义前景色和背景色信息)编辑文本时,我当前的实现可以正常工作。 But when storing the edited document in a file I get improper structured HTML and the parts of the text that were entered using a specific style are missing. 但是,当将编辑后的文档存储在文件中时,我得到的结构化HTML不正确,并且缺少使用特定样式输入的部分文本。 Here is my code: 这是我的代码:

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.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.MutableAttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.Style;
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) {
        final SimpleEditor editor = new SimpleEditor();
        editor.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        editor.setVisible(true);
    }

    public SimpleEditor() {
        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();
        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 Style style = textPane.getStyle(selItem);
                textPane.setCharacterAttributes(extractStyleAttribs(style), true);
                SimpleEditor.this.requestFocus();
            }
        });
        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 ExitAction actSave = new ExitAction();
        mnuFile.add(actSave);
        return menubar;
    }

    class ExitAction extends AbstractAction {
        private static final long serialVersionUID = 1L;
        public ExitAction() {
            super("Save & Exit");
        }
        @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) {
                    }
                }
            }
            System.exit(0);
        }
    }
}

Here a screenshot of the application with some styled text entered: 这里是输入了一些样式文本的应用程序的屏幕截图: 带有一些彩色文本的应用程序

The HTML file which is created when I save the document ( textPane.write(writer); ) is not properly structured. 保存文档时创建的HTML文件( textPane.write(writer); )的结构不正确。 The <body> ... </body> part looks as follows: <body> ... </body>部分如下所示:

<body>
    <p style="margin-top: 0">
      default text
    </p>
    <p style="margin-top: 0">
      <font color="#cc0000"><p style="background-color: silver">
</font>    </p>
    <p style="margin-top: 0">
      <font color="#0000cc"><p style="background-color: aqua">
</font>    </p>
    <p style="margin-top: 0">
      <font color="#333333" face="Dialog" size="3"><p FONT_ATTRIBUTE_KEY="javax.swing.plaf.FontUIResource[family=Dialog,name=Dialog,style=plain,size=12]">
</font>    </p>
</body>

It is quite obvious that the generated HTML code is not correct. 很明显,生成的HTML代码不正确。 Inside a <p> element a new <font> element is created which defines the style's foreground color. <p>元素内,将创建一个新的<font>元素,该元素定义样式的前景色。 Then another <p> element with the definition of the background color is created. 然后,创建另一个具有背景色定义的<p>元素。 But the text is missing. 但是文本丢失了。 Then instead of the closing </p> tag the closing </font> tag follows and afterwards the </p> tag closing the outer <p> element. 然后,紧随其后的是</p> </font>标记,而不是</p>标记,然后是</p>标记关闭外部<p>元素。 What am I doing wrong? 我究竟做错了什么?

After lots of reseach I found a simple solution for my problem. 经过大量研究后,我找到了解决问题的简单方法。 See here . 这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM