Ich versuche eine JTextPane
zu verwenden, um etwas HTML zu rendern und ein CSS Stylesheet darauf anzuwenden. Das heißt, ich verwende HTMLEditorKit
und StyleSheet
Klassen. Ich weiß, dass alle HTMLEditorKits
teilen die gleiche Standard StyleSheet
Instanz, wenn Sie also dieses Standard-Stylesheet-Objekt ändern, Sie Änderungen auf Anwendungsebene anwenden (alle Komponenten, die HTML rendern).Wie initialisiert man ein JTextPane StyleSheet richtig, so dass keine andere HTML-fähige Komponente vom Stil betroffen ist?
Aber in meinem Beispiel dachte ich, dass ich dies vermieden hatte, indem ich meine eigene StyleSheet
Instanz basierend auf dem Standard erstellt. Dies funktioniert jedoch nicht, wie auf dem angezeigten JTree
ersichtlich ist, der nach dem Stylesheet rendert, das nur auf die JTextPane
angewendet werden sollte.
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 + " <i>" + mynode.argument);
}
}
return this;
}
}
}
Also wie kann man richtig diese Objekte initialisieren, so dass es kein CSS Verschütten über die Anwendung ist (so dass Textbereich macht CSS nach, doch der Baum nicht)?
Hinweis: Die rote Unterstreichung im obigen Bild zeigt das Problem mit dem Überlaufen an und wurde später von mir hinzugefügt (nein, es ist nicht der Renderer).