我试图让JEditorPane保留任何CSS字体样式。不幸的是,它似乎完全剥离了段落标签(以及其他标签)并将其转换为A标签的字体标签。
考虑以下示例:
import java.awt.BorderLayout;
import java.awt.Container;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.WindowConstants;
public class EditorPaneTest
{
public static void main(String[] args)
{
String text = "<html><head></head><body><p style=\"padding-right: 10px; padding-left: 10px; font-size: 14px; line-height: 125%; font-family: Verdana;\">This is a test.</p>"
+ "<p><a href=\"http://www.google.com/\" style=\"font-size: 9px; margin-right: 10px; font-style: normal; font-family: Verdana;\">Google</a></p></body></html>";
JEditorPane editorPane = new JEditorPane("text/html", text);
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
Container contentPane = frame.getContentPane();
contentPane.setLayout(new BorderLayout());
contentPane.add(new JScrollPane(editorPane), BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
text = editorPane.getText();
System.out.println(text);
}
}
这会为p和a标签生成以下输出:
<p style="padding-left: 10px; padding-right: 10px; line-height: 125%">
和
<a href="http://www.google.com/" style="margin-right: 10px"><font size="9px" face="Verdana">Google</font></a>
如您所见,它保留了填充和边距样式,但删除了段落标记的字体样式,并将其转换为A标记的字体标记。
在调用getText
之前,如果显示它,它实际上会正确设置段落的样式。
如何获取它以保持字体属性不变?
答案 0 :(得分:2)
确定,
问题肯定在HTMLWriter
课程中。不幸的是,他们并没有轻易覆盖这个课程,但我相信我拥有它。
import java.io.IOException;
import java.io.Writer;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.text.AttributeSet;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.html.CSS;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLWriter;
public class FixedHTMLWriter extends HTMLWriter
{
private Vector tags = new Vector(10);
private Vector tagValues = new Vector(10);
private Vector tagsToRemove = new Vector(10);
private MutableAttributeSet convAttr = new SimpleAttributeSet();
private MutableAttributeSet oConvAttr = new SimpleAttributeSet();
public FixedHTMLWriter(Writer w, HTMLDocument doc, int pos, int len)
{
super(w, doc, pos, len);
}
AttributeSet convertToHTML(AttributeSet from, MutableAttributeSet to)
{
if (to == null)
{
to = convAttr;
}
to.removeAttributes(to);
if (from != null)
{
Enumeration keys = from.getAttributeNames();
String value = "";
while (keys.hasMoreElements())
{
Object key = keys.nextElement();
if (key instanceof CSS.Attribute)
{
value += key + ": " + from.getAttribute(key) + ";";
if (keys.hasMoreElements())
value += " ";
}
else
{
to.addAttribute(key, from.getAttribute(key));
}
}
if (value.length() > 0)
{
to.addAttribute(HTML.Attribute.STYLE, value);
}
}
return to;
}
@Override
protected void closeOutUnwantedEmbeddedTags(AttributeSet attr) throws IOException
{
tagsToRemove.removeAllElements();
// translate css attributes to html
attr = convertToHTML(attr, null);
HTML.Tag t;
Object tValue;
int firstIndex = -1;
int size = tags.size();
// First, find all the tags that need to be removed.
for (int i = size - 1; i >= 0; i--)
{
t = (HTML.Tag) tags.elementAt(i);
tValue = tagValues.elementAt(i);
if ((attr == null) || noMatchForTagInAttributes(attr, t, tValue))
{
firstIndex = i;
tagsToRemove.addElement(t);
}
}
if (firstIndex != -1)
{
// Then close them out.
boolean removeAll = ((size - firstIndex) == tagsToRemove.size());
for (int i = size - 1; i >= firstIndex; i--)
{
t = (HTML.Tag) tags.elementAt(i);
if (removeAll || tagsToRemove.contains(t))
{
tags.removeElementAt(i);
tagValues.removeElementAt(i);
}
write('<');
write('/');
write(t.toString());
write('>');
}
// Have to output any tags after firstIndex that still remaing,
// as we closed them out, but they should remain open.
size = tags.size();
for (int i = firstIndex; i < size; i++)
{
t = (HTML.Tag) tags.elementAt(i);
write('<');
write(t.toString());
Object o = tagValues.elementAt(i);
if (o != null && o instanceof AttributeSet)
{
writeAttributes((AttributeSet) o);
}
write('>');
}
}
}
private boolean noMatchForTagInAttributes(AttributeSet attr, HTML.Tag t, Object tagValue)
{
if (attr != null && attr.isDefined(t))
{
Object newValue = attr.getAttribute(t);
if ((tagValue == null) ? (newValue == null) : (newValue != null && tagValue.equals(newValue)))
{
return false;
}
}
return true;
}
@Override
protected void writeEmbeddedTags(AttributeSet attr) throws IOException
{
// translate css attributes to html
attr = convertToHTML(attr, oConvAttr);
Enumeration names = attr.getAttributeNames();
while (names.hasMoreElements())
{
Object name = names.nextElement();
if (name instanceof HTML.Tag)
{
HTML.Tag tag = (HTML.Tag) name;
if (tag == HTML.Tag.FORM || tags.contains(tag))
{
continue;
}
write('<');
write(tag.toString());
Object o = attr.getAttribute(tag);
if (o != null && o instanceof AttributeSet)
{
writeAttributes((AttributeSet) o);
}
write('>');
tags.addElement(tag);
tagValues.addElement(o);
}
}
}
@Override
protected void writeAttributes(AttributeSet attr) throws IOException
{
convAttr.removeAttributes(convAttr);
convertToHTML(attr, convAttr);
Enumeration names = convAttr.getAttributeNames();
while (names.hasMoreElements())
{
Object name = names.nextElement();
if (name instanceof HTML.Tag || name instanceof StyleConstants || name == HTML.Attribute.ENDTAG)
{
continue;
}
write(" " + name + "=\"" + convAttr.getAttribute(name) + "\"");
}
}
}
您需要覆盖HTMLEditorKit
类方法write
,如下所示:
public void write(Writer out, Document doc, int pos, int len) throws IOException, BadLocationException
{
if (doc instanceof HTMLDocument)
{
FixedHTMLWriter w = new FixedHTMLWriter(out, (HTMLDocument) doc, pos, len);
w.write();
}
else if (doc instanceof StyledDocument)
{
MinimalHTMLWriter w = new MinimalHTMLWriter(out, (StyledDocument) doc, pos, len);
w.write();
}
else
{
super.write(out, doc, pos, len);
}
}
使用对HTMLEditorKit
的调用,在JEditorPane
上设置被覆盖的setEditorKit
。