Returns the text contained in this TextComponentin terms of the content type of this editor.
Wahrscheinlich läuft bei dieser Methode etwas schief… Muss es unbedingt ein JEditorPane sein, ginge nicht vielleicht auch eine JTextArea, wenn es eh um Plain-Text geht?
Man sollte sich dazu vllt. mal die von JEditorPane überschriebenen get- und setText-Methoden im Quelltext ansehen. Wenn mich nicht alles täuscht, dan wird bei setText ein EditorKit verwendet, bei getText jedoch nicht. Ich würde nun rein Intuitiv, dieses EditorKit kopieren, bevor ich den Text kopiere.
Bei nochmaligem Überlegen, würde ich die JEditorPane erweitern, in welcher ich die getText-Methode überschreibe, die dann analog zu setText einen Writer über kit.write() beschreibt.
Außerdem fuchtele ich hier noch mit einem JDK 8 rum und von daher weiß ich nicht, ob dieser „Fauxpas“ (so will ich das mal nennen) inzwischen behoben wurde.
Das macht überhaupt nichts. Wichtig ist vermutlich nur der ContentType und der wird samt Charset und weiteren möglichen Parametern im EditorKit gespeichert. Wenn ContentType und/oder EditorKit gar nicht beachtet werden, dann werden automatisch Defaults gesetzt und wenn diese nicht mit der Quelle identisch sind, wird auch nicht 1:1 kopiert - ist doch logisch, oder?
Und noch was: Wenn ich weiß, dass ich mit HTML arbeite (was ja bei JEditorPane der Fall ist), dann würde ich bei Sonderzeichen ohnehin mit HTML-En- bzw. -Decode arbeiten, aber das ist wohl nicht mehr nötig, sobald ContentType und Charset passt.
Also das ist richtig, getText() liefert HTML und das wird bei setText() auch interpretiert, allerdings wird zum Beispiel ein Tabulator nicht codiert, aber in p1 als Tabulator dargestellt.
Allerdings gibt es einen „Trick“: Wenn man in p2 etwas schreibt, dann ist setText() korrekt. Ich vermute, sobald man etwas eintippt, wird der ContentType, das Charset usw. gesetzt.
Wann immer getEditorKit() oder getEditorKitForContentType() aufgerufen wird, wird eines erstellt, wenn keines vorhanden ist. Das ist z.B. auch bei setText() der Fall, also ist es egal, ob vorher etwas eingetippt wurde, oder nicht. setText() wird ja auch bei Eingabe über den EDT aufgerufen, soweit ich weiß.
Und ja, natürlich ist es ein Bug, wenn eine get-Methode anders arbeitet, als eine set-Methode.
Dennoch kurz der Hinweis, dass p1.setContentType("text/plain");
und p1.setEditorKit(new HTMLEditorKit());
die erste Anweisung unsinnig ist (denn nach dem Setzen von HTMLEditorKit sollte der ContentType eigentlich „text/html“ sein…).
Das würde als „Workaround“ funktionieren:
JFrame f = new JFrame();
f.setLayout(new GridLayout(1, 3, 10, 0));
JEditorPane p1 = new JEditorPane();
JEditorPane p2 = new JEditorPane();
HTMLEditorKit e1 = new HTMLEditorKit();
HTMLEditorKit e2 = new HTMLEditorKit();
p1.setEditorKitForContentType("text/html", e1); // also "text/plain"
p2.setEditorKitForContentType("text/html", e2);
JPanel p3 = new JPanel();
JButton b = new JButton("replace");
p3.add(b);
f.add(p1);
f.add(p2);
f.add(p3);
b.addActionListener((e) -> {
System.out.println(p1.getText());
p2.setText(p1.getText());
});
f.setSize(800, 400);
f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
f.setVisible(true);
Die Details des Zusammenspiels zwischen „Document“ und „Component“ sind ziemlich tricky (was nicht verwunderlich ist, wenn man bedenkt, dass man da „einfach mal so“ auch HTML darstellen kann), und ich fräse mich da immer nur so weit rein, wie ich es gerade brauche (und bisher habe ich noch nicht viel davon gebraucht…).
Zumindest nimmt er, wenn man über’s Document geht, die Tabs mit, und der Beschreibung nach war das ja vermutlich das, was du suchtest…
doc1.getText(...); liefert keinen HTML-Text zurück, deshalb funktioniert das…
Also mir fallen als Workaround nur diese zwei Möglichkeiten ein:
doc1.getText(...); oder
p1.setEditorKitForContentType("text/html", new HTMLEditorKit());,
wobei 1. womöglich besser ist.
Edit: Denn HTML(-Text) und Tabulatorzeichen können zusammen nicht richtig transportiert oder dargestellt werden. HTML sieht glaube ich keine Tabulatorzeichen vor…
Ja, in diesem Sinne ist der Text vom Document das „Model“, und der Text der JEditorPane selbst ist die „View“.
Da passiert halt viel magisches: Wenn man so einer JEditorPane etwas gibt, was in <html> tags steht, wird das interpretiert, durch das EditorKit und andere Sachen durchgejagt, und am Ende kommt formatierter Text auf dem Bildschirm raus. Wenn man dem Document aber „plain Text“ gibt, dann wird dieser Plain Text praktisch mit HTML formatiert, und beim JEditorPane hat man dann den HTML-Code, den man brauch, um den plain Text formatiert darzustellen.
Man könnte auch doc2.insertString(0, tacomment1.getText(), null); machen, um sich ~„den HTML-Quellcode“ anzuschauen.
(Ein Tab geht theoretisch mit &tab; - warum das nicht so codiert wird, ist eine der Detailfragen, mit denen man sich lange beschäftigen kann).
Gibt es &tab; überhaupt (anscheinend nicht, sonst wäre es auch übersetzt worden)? Ich verwende da immer „& # 0 9 ;“. Und genauso würde es auch codiert, wenn die setText()- mit der getText()-Methode übereinstimmen würde. Der Workaround mit Document funktioniert eigentlich bei jeder JTextComponent nur leider bei der JEditorPane nicht immer, wenn die EditorKits nicht „equal“ sind.
Als „Workaround“ würde ich das nicht direkt bezeichnen. Wenn man sowas hat wie <html>Hello</html>
und fragt, „Was ist der ‚text‘“, dann wäre Hello eine legitme Antwort. Der Rest ist Formatierung.
Dass das „Document“ eine „low-level-Variante“ des Textes speichert, und „vor“ den Dingen wie EditorKit und Attributes liegt, ändert daran ja nichts. Aber wie gesagt: Es ist kompliziert. Und außer für sowas wie die Suchfunktion in Common und CommonUI - nur ein paar Utility-Klassen habe ich mich damit noch nicht soooo im Detail beschäftigt.
Das ist vermutlich das Entscheidende und die Krux am JEditorPane. Das EditorKit wird, soweit ich das überblicke, nur von dieser Klasse verwendet und deswegen überschreibt JEditorPane auch set- und getText() von JTextComponent. Bei getText() wird das Kit nicht verwendet, also bekommt man das, was im document steht. Und im document steht formatierter HTML-Text, weil es per überschiebener setText()-Methode dort formatiert eingepflegt wird. Greift man direkt auf document zu und kopiert auf diese Art, dann umgeht man das EditorKit und deswegen ist es für mich ein Workaround. An die legitime Antwort („Hello“) kommt man damit deswegen afaik auch nicht mehr, es sei denn, man hat das document mit diesem WA aus einer JTextComponent befüllt.
Das Ganze ist mMn nicht nur ein Bug, sondern ein unheimlich ekliger Pitfall. Vermutlich ist CBs Idee mit der JTextArea gar nicht mal eine soooo Üble.