我希望在JTextField
中的文本末尾检索换行符,但是将文本字段的文本设置为我的字符串后,已将其修改为空格字符。下面的代码突出了问题所在。
是否可以在文本字段中保留\n
?
import javax.swing.JTextField;
public class StackOver {
public static void main(String[] args) {
String hasNewLineEscapeCharacter = makeStringWithNewLineCharacter();
JTextField backgroundText = new JTextField(90);
backgroundText.setText(hasNewLineEscapeCharacter);
char spaceChar = backgroundText.getText().charAt(backgroundText.getText().length()-1);
char newLineChar = hasNewLineEscapeCharacter.charAt(needsNewLineEscapeCharacter.length()-1);
}
public static String makeStringWithNewLineCharacter() {
String str = "hello,world!";
str += ('\n');
return str;
}
}
答案 0 :(得分:2)
是否可以在我的JTextField中保留'\ n'?
JTextField
使用PlainDocument
,其中包含一个过滤“ \ n”并将其替换为空格字符的属性。
要在文本字段中保留换行符,您可以尝试:
textField.getDocument().putProperty("filterNewlines", Boolean.FALSE);
但是,这将导致文本像文本区域一样显示在两行上。
因此,如上所述,您应该只使用JTextArea。
无法在一行上显示包含换行符的文本。
您可能想做的是在文本字符串中存储其他无法打印的字符,然后如果需要访问带有换行符的文本,则使用String.replaceAll(...)。
答案 1 :(得分:0)
如果您希望 JTextField
不仅显示,而且在用户按下 Enter 键时接受 换行符,您还需要添加一个 ActionListener
。如果您将 JTextField
子类化(您可以改用 工厂方法),它可能如下所示:
public class JMultilineTextField extends JTextField {
public JMultilineTextField() {
addActionListener(e -> {
try {
final int selectionStart = getSelectionStart();
final int selectionEnd = getSelectionEnd();
final Document document = getDocument();
if (selectionStart != selectionEnd) {
document.remove(selectionStart, selectionEnd - selectionStart);
}
document.insertString(selectionStart, "\n", null);
} catch (final BadLocationException ble) {
// Unlikely to happen, but add your error handling code here.
ble.printStackTrace();
}
});
}
}
但这带来了另一个问题:随着新行的添加或删除,您的 JTextField
将垂直增长或缩小,并且您需要父组件来反映文本字段大小的变化并相应地布局其子项(否则,您很可能最终会出现重叠的 Swing 组件)。可以通过在文本字段的 DocumentListener
中安装 Document
来解决此问题:
public class JMultilineTextField extends JTextField {
// ...
@Override
public void setDocument(final Document doc) {
setupDocument(doc);
super.setDocument(doc);
}
private void setupDocument(final Document doc) {
doc.putProperty("filterNewlines", false);
installDocumentListenerIfNecessary(doc);
}
private void installDocumentListenerIfNecessary(final Document doc) {
final DocumentListener documentListeners[] = ((AbstractDocument) doc).getListeners(DocumentListener.class);
if (Stream.of(documentListeners).noneMatch(documentListener -> documentListener instanceof RowCountChangeListener)) {
doc.addDocumentListener(new RowCountChangeListener());
}
}
private final class RowCountChangeListener implements DocumentListener {
@Override
public void insertUpdate(final DocumentEvent e) {
revalidateParentIfNecessary();
}
@Override
public void removeUpdate(final DocumentEvent e) {
revalidateParentIfNecessary();
}
@Override
public void changedUpdate(final DocumentEvent e) {
revalidateParentIfNecessary();
}
private void revalidateParentIfNecessary() {
final JMultilineTextField textField = JMultilineTextField.this;
final Dimension currentSize = textField.getSize();
final Dimension preferredSize = textField.getPreferredSize();
/*
* Grow/shrink vertically as necessary.
*/
if (currentSize.height != preferredSize.height) {
textField.getParent().revalidate();
}
}
}
}
我还建议您从文本字段的构造函数中调用 setupDocument()
:
public class JMultilineTextField extends JTextField {
public JMultilineTextField() {
setupDocument(getDocument());
// add ActionListener, etc.
}
// ...
}