gpt4 book ai didi

java - 如何正确初始化 JTextPane 样式表,使其他启用 HTML 的组件不受该样式的影响?

转载 作者:搜寻专家 更新时间:2023-11-01 02:37:39 26 4
gpt4 key购买 nike

我正在尝试使用 JTextPane 呈现一些 HTML 并对其应用 CSS 样式表。这意味着我正在使用 HTMLEditorKitStyleSheet 类。我知道所有 HTMLEditorKits 共享相同的默认 StyleSheet 实例,因此如果您更改此默认样式表对象,您将在应用程序级别(所有呈现 HTML 的组件)应用更改。

但在我的示例中,我认为我已经通过基于默认创建自己的 StyleSheet 实例来避免这种情况。然而,这不起作用,如显示的 JTree 所示,它根据仅打算应用于 JTextPane 的样式表呈现。

import java.awt.*;
import javax.swing.*;
import javax.swing.text.html.*;
import javax.swing.tree.*;

public class TextPaneCssSpill extends JFrame {

private JTextPane textPane;
private JTree tree;
private JSplitPane splitPane;

public TextPaneCssSpill() {
HTMLEditorKit hed = new HTMLEditorKit();
StyleSheet defaultStyle = hed.getStyleSheet();
StyleSheet style = new StyleSheet();
style.addStyleSheet(defaultStyle);
style.addRule("body {font-family:\"Monospaced\"; font-size:9px;}");
style.addRule("i {color:#bababa; font-size:9px;}"); // gray italic
hed.setStyleSheet(style);

textPane = new JTextPane();
textPane.setEditorKit(hed);
textPane.setDocument(hed.createDefaultDocument());

DefaultMutableTreeNode root = new DefaultMutableTreeNode(new MyNode("name", "argument"), true);
root.add(new DefaultMutableTreeNode(new MyNode("name", "argument"), false));
root.add(new DefaultMutableTreeNode(new MyNode("name", "argument"), false));
root.add(new DefaultMutableTreeNode(new MyNode("name", "argument"), false));
root.add(new DefaultMutableTreeNode(new MyNode("name", "argument"), false));

tree = new JTree(root);
tree.setCellRenderer(new MyNodeTreeRenderer());

setLayout(new BorderLayout());
splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, textPane, tree);
add(splitPane);

pack();
setLocationRelativeTo(null);
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new TextPaneCssSpill().setVisible(true);
}
});
}

private static class MyNode {
private final String name;
private final String argument;

public MyNode(String name, String argument) {
this.name = name;
this.argument = argument;
}

@Override
public String toString() {
return name + " " + argument;
}
}

private static class MyNodeTreeRenderer extends DefaultTreeCellRenderer {

@Override
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
if (value instanceof DefaultMutableTreeNode) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
if (node.getUserObject() instanceof MyNode) {
MyNode mynode = (MyNode) node.getUserObject();
setText("<html>" + mynode.name + "&nbsp;<i>" + mynode.argument);
}
}
return this;
}

}
}

rendered example

那么如何正确地初始化这些对象,使应用程序中没有 CSS 溢出(以便文本 Pane 根据 CSS 呈现,而树却没有)?

注意:上图中红色下划线表示溢出问题,是我后来添加的(不是,不是渲染器)。

最佳答案

我的代码中有问题的部分是调用 HTMLEditorKit.setStyleSheet(style);。这替换了 all HTMLEditorKits 的默认样式表实例,这是我不知道的。

    /**
* Set the set of styles to be used to render the various
* HTML elements. These styles are specified in terms of
* CSS specifications. Each document produced by the kit
* will have a copy of the sheet which it can add the
* document specific styles to. By default, the StyleSheet
* specified is shared by all HTMLEditorKit instances.
* This should be reimplemented to provide a finer granularity
* if desired.
*/
public void setStyleSheet(StyleSheet s) {
if (s == null) {
AppContext.getAppContext().remove(DEFAULT_STYLES_KEY);
} else {
AppContext.getAppContext().put(DEFAULT_STYLES_KEY, s);
}
}

/**
* Get the set of styles currently being used to render the
* HTML elements. By default the resource specified by
* DEFAULT_CSS gets loaded, and is shared by all HTMLEditorKit
* instances.
*/
public StyleSheet getStyleSheet() {
AppContext appContext = AppContext.getAppContext();
StyleSheet defaultStyles = (StyleSheet) appContext.get(DEFAULT_STYLES_KEY);

if (defaultStyles == null) {
defaultStyles = new StyleSheet();
appContext.put(DEFAULT_STYLES_KEY, defaultStyles);
try {
InputStream is = HTMLEditorKit.getResourceAsStream(DEFAULT_CSS);
Reader r = new BufferedReader(
new InputStreamReader(is, "ISO-8859-1"));
defaultStyles.loadRules(r, null);
r.close();
} catch (Throwable e) {
// on error we simply have no styles... the html
// will look mighty wrong but still function.
}
}
return defaultStyles;
}

因此需要做的是扩展 HTMLEditorKit 使其在不更改默认值的情况下返回您的样式表。

import java.awt.*;
import java.io.IOException;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.text.html.*;
import javax.swing.tree.*;

public class TextPaneCssSpill extends JFrame {

private JTextPane textPane;
private JTree tree;
private JSplitPane splitPane;
private StyleSheet style;

public TextPaneCssSpill() {
MyHTMLEditorKit hed = new MyHTMLEditorKit();
StyleSheet defaultStyle = hed.getDefaultStyleSheet();
style = new StyleSheet();
style.addStyleSheet(defaultStyle);
style.addRule("body {font-family:\"Monospaced\"; font-size:9px;}");
style.addRule("i {color:#bababa; font-size:9px;}"); // gray italic
hed.setStyleSheet(style);

textPane = new JTextPane();
textPane.setEditorKit(hed);
textPane.setDocument(hed.createDefaultDocument());
appendHtmlToTextPane("<i>our gray italic text</i>", textPane);

DefaultMutableTreeNode root = new DefaultMutableTreeNode(new MyNode("name", "argument"), true);
root.add(new DefaultMutableTreeNode(new MyNode("name", "argument"), false));
root.add(new DefaultMutableTreeNode(new MyNode("name", "argument"), false));
root.add(new DefaultMutableTreeNode(new MyNode("name", "argument"), false));
root.add(new DefaultMutableTreeNode(new MyNode("name", "argument"), false));

tree = new JTree(root);
tree.setCellRenderer(new MyNodeTreeRenderer());

setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new BorderLayout());
splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, textPane, tree);
add(splitPane);

pack();
setLocationRelativeTo(null);
}

private void appendHtmlToTextPane(String str, JTextPane pane) {
Document doc = pane.getDocument();
if (doc != null) {
if (doc instanceof HTMLDocument) {
HTMLDocument htmlDoc = (HTMLDocument) doc;
Element html = htmlDoc.getDefaultRootElement();
if (HTML.Tag.HTML.toString().equalsIgnoreCase(html.getName())) {
Element body = null;
for (int i = 0; i < html.getElementCount(); i++) {
Element element = html.getElement(i);
if (element.getAttributes().getAttribute(StyleConstants.NameAttribute) == HTML.Tag.BODY) {
body = element;
break;
}
}
if (HTML.Tag.BODY.toString().equalsIgnoreCase(body.getName())) {
try {
htmlDoc.insertBeforeEnd(body, str);
Element lastLine = body.getElement(body.getElementCount() - 1);
int end = lastLine.getStartOffset();
textPane.setCaretPosition(end);

} catch (BadLocationException e) {
} catch (IOException ex) {
}
}
}
}
}
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new TextPaneCssSpill().setVisible(true);
}
});
}

private static class MyNode {
private final String name;
private final String argument;

public MyNode(String name, String argument) {
this.name = name;
this.argument = argument;
}

@Override
public String toString() {
return name + " " + argument;
}
}

private static class MyNodeTreeRenderer extends DefaultTreeCellRenderer {

@Override
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
if (value instanceof DefaultMutableTreeNode) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
if (node.getUserObject() instanceof MyNode) {
MyNode mynode = (MyNode) node.getUserObject();
setText("<html>" + mynode.name + "&nbsp;<i>" + mynode.argument);
}
}
return this;
}

}

/**
* Avoid setting the stylesheet for all HTMLEditorKit instances.
*/
private static class MyHTMLEditorKit extends HTMLEditorKit {

private StyleSheet myStyle;

@Override
public StyleSheet getStyleSheet() {
return myStyle == null ? super.getStyleSheet() : myStyle;
}

@Override
public void setStyleSheet(StyleSheet s) {
this.myStyle = s;
}

public StyleSheet getDefaultStyleSheet() {
return super.getStyleSheet();
}

public void setDefaultStyleSheet(StyleSheet s) {
super.setStyleSheet(s);
}

}
}

fixed version

关于java - 如何正确初始化 JTextPane 样式表,使其他启用 HTML 的组件不受该样式的影响?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43408539/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com