Java Swing-My类扩展了JTextPane,并首先调用My append(),然后调用super.setText()添加额外的换行符
很简单:我有一个SSCCE:Java Swing-My类扩展了JTextPane,并首先调用My append(),然后调用super.setText()添加额外的换行符,java,swing,jtextpane,Java,Swing,Jtextpane,很简单:我有一个SSCCE: import java.io.File; import javax.swing.JFrame; import javax.swing.JTextPane; import javax.swing.SwingUtilities; import javax.swing.text.BadLocationException; import javax.swing.text.Document; import javax.swing.text.MutableAttributeS
import java.io.File;
import javax.swing.JFrame;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import net.miginfocom.swing.MigLayout;
public class Test1_ChangeStyleAndAppend extends JFrame {
public class MyJTextPane extends JTextPane {
/**
* Append some text to this pane.
* @param s
*/
public void append(String s) {
try {
Document doc = this.getDocument();
doc.insertString(doc.getLength(), s, null);
} catch(BadLocationException e) {
System.err.println(e);
}
}
/**
* Append some text and change line.
* @param s
*/
public void appendLine(String s) {
try {
Document doc = this.getDocument();
doc.insertString(doc.getLength(), s + System.lineSeparator(), null);
} catch(BadLocationException e) {
System.err.println(e);
}
}
}
public Test1_ChangeStyleAndAppend() {
begin();
}
private void begin() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
MyJTextPane pane0 = new MyJTextPane();
pane0.appendLine("MyJTextPane using append() and then calling setText()");
pane0.appendLine("Second line. ");
pane0.appendLine("Third line");
pane0.setText(pane0.getText() + "At last" + System.lineSeparator());
pane0.setBorder(new EtchedBorder(EtchedBorder.RAISED));
add(pane0, BorderLayout.NORTH);
MyJTextPane pane = new MyJTextPane();
// changeLineSpacing(pane, 1.5f, false);
pane.appendLine("MyJTextPane calling appendLine()");
pane.appendLine("Second line. ");
pane.appendLine("Third line");
pane.appendLine("At last");
pane.setBorder(new EtchedBorder(EtchedBorder.RAISED));
add(pane, BorderLayout.CENTER);
JTextPane pane2 = new JTextPane();
pane2.setText("Normal JTextPane calling setText()");
pane2.setText(pane2.getText() + System.lineSeparator() + "Second line. ");
pane2.setText(pane2.getText() + System.lineSeparator() + "Third line");
pane2.setText(pane2.getText() + System.lineSeparator() + "At last");
pane2.setBorder(new EtchedBorder(EtchedBorder.RAISED));
add(pane2, BorderLayout.SOUTH);
pack();
setVisible(true);
}
/**
* Select all the text of a <code>JTextPane</code> first and then set the line spacing.
* @param pane the <code>JTextPane</code> to apply the change
* @param factor the factor of line spacing. For example, <code>1.0f</code>.
* @param replace whether the new <code>AttributeSet</code> should replace the old set. If set to <code>false</code>, will merge with the old one.
*/
public static void changeLineSpacing(JTextPane pane, float factor, boolean replace) {
pane.selectAll();
MutableAttributeSet set = new SimpleAttributeSet(pane.getParagraphAttributes());
StyleConstants.setLineSpacing(set, factor);
pane.setParagraphAttributes(set, replace);
pane.setCaretPosition(0); //scroll to the top.
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Test1_ChangeStyleAndAppend frame = new Test1_ChangeStyleAndAppend();
}
});
}
}
结果是:
我喜欢窗户
我有两个文本窗格,一个是JTextPane
,另一个是我的类扩展JTextPane
,在这一个中,我在自定义类中定义了两个方便的方法,append()
和appendLine()
,但我没有覆盖supergetText()
方法
现在,当我在类中调用appendLine()
然后调用setText()
时,调用getText()
会在行之间添加另一个\r
,使其\r\n
并在两行之间添加额外的空行。这不是我想要的,我不想添加\r
我有一个类型为JTextArea
的变量,为了更改行距,我将其更改为JTextPane
,因为JTextArea
不能有可调整的行距。但是它在整个项目中以及在使用pane.setText(pane.getText+newText)
时都会出现。现在我必须搜索所有出现的setText()
,并将其更改为appendLine()
。在做这个大的改变之前,我想了解为什么要添加这个额外的\r
如果我总是调用append()
或总是调用setText(pane.getText()+newText)
,则不会发生这种情况。但是如果我先调用append()
,然后调用setText(pane.getText()+newText)
,就会添加\r
有人对此进行了说明?Windows的行分隔符为“\r\n” 文档仅对新行字符串使用“\n”
//doc.insertString(doc.getLength(), s + System.lineSeparator(), null);
doc.insertString(doc.getLength(), s + "\n", null);
不确定到底是什么问题,但在insertString(…)和getText()方法之间,换行符字符串的处理方式存在不一致之处
简单的解决方案是使用其新行字符串更新文档,而不是平台换行字符串
//doc.insertString(doc.getLength(), s + System.lineSeparator(), null);
doc.insertString(doc.getLength(), s + "\n", null);
编辑:错误报告和存档。仅在Windows中发生。我使用Windows 10 上一个答案之所以被接受,是因为我已经多次接受我的答案,以此来解决我的问题:)是时候向别人表示一些慷慨了,这样我们才能继续互相帮助 ========================================================================= 最后,当我触摸下面的文档时,我认为问题出现了。我猜,这是因为
JTextPane
使用StringWriter获取其内容,但这是错误的。在JDK 8u111源代码中,我发现:
/**
* Returns the text contained in this <code>TextComponent</code>
* in terms of the
* content type of this editor. If an exception is thrown while
* attempting to retrieve the text, <code>null</code> will be returned.
* This is implemented to call <code>JTextComponent.write</code> with
* a <code>StringWriter</code>.
*
* @return the text
* @see #setText
*/
public String getText() {
String txt;
try {
StringWriter buf = new StringWriter();
write(buf);
txt = buf.toString();
} catch (IOException ioe) {
txt = null;
}
return txt;
}
StringWriter
可能做了一些错误的事情来生成额外的\r
。因为如果我用接触文档的方法覆盖此方法,问题就消失了,所有输出都正常,\n
或System.lineseparator()
我有这个SSCCE:
-那不是SSCCE。MigLayout不是JDK的一部分。没有理由使用第三方版面管理器,因为您的问题与版面管理器无关。只需使用GridLayout。您好,我没有理由,但是如果您将System.lineSeparator()替换为appendLine方法,您将在第一个和第二个texpane中获得相同的结果。抱歉@camickr我忘记了这一点。我会更改它。@JulienGauthier谢谢,但你说“将System.lineSeparator()`替换为我的方法”时,我不明白你的意思。你想说“去掉这部分”?我添加它是为了节省每次添加新行的工作量,这就是为什么它被称为appendLine()
,以区别于append()
。我在第二个面板中使用了appendLine()
,并且没有添加额外的换行符…我已经编辑了问题以使用BorderLayout
。我希望这能有所帮助,有人能帮上忙。提前谢谢。你说得对,谢谢卡米克。原因不得而知,但我看到了这一点:调用pane.getText()
时,它使用StringWriter buf=newstringwriter();写入(buf);txt=buf.toString()代码>。这里可能就是问题发生的地方。如果我使用此代码获取文本:请尝试{string=pane0.getDocument().getText(0,pane0.getDocument().getLength());}catch(BadLocationException e){e.printStackTrace();}
并将“\n”
更改回系统.lineSeparator()
,问题消失。错误报告给Oracle并等待。再次感谢。