【发布时间】:2013-07-06 04:30:08
【问题描述】:
首先我希望我开始一个新话题不是问题。 Tbh 我不知道如何根据已经回答的问题提出问题,所以我做了这个。
我对 Java 很陌生,我的问题如下。我正在编写一个小聊天程序,并使用JEditorPane 和HTMLEditorKit 来显示不同颜色的文本、显示笑脸和显示超链接。
我的问题是,经过一些研究,我发现问题可能是由于 Java7 引起的,我无法让换行符正常工作。我希望文本自动换行并在超过组件宽度的字符串中间换行。
自动换行可以正常工作,但如果有人输入了一个很长的字符串,JEditorPane 会被扩展,您需要调整框架的大小以将所有内容都显示在屏幕上,这是我不希望发生的。
我已经尝试了一些解决这个问题的方法,但它们只允许换行,这样换行就不再起作用了。除此之外,我希望用户能够通过按 Enter 来换行他的文本。为此,我将 \n 添加到文本中,并且通过修复,这将不再影响结果,所有内容都将显示在一行中。
我觉得我已经在网络上花费了数年时间来寻找解决方案,但现在我的情况没有任何效果,特别是因为它似乎一直都是相同的解决方案。我希望你们能帮助我。
概括地说:
我有什么:
- 如果长字符串由空格分隔,则换行
- 如果您使用 Windows 并且您的输入包含通过回车创建的换行,它们也会换行
- 如果您输入的字符串很长且没有空格,则面板会展开,您需要调整框架大小
- HTML 格式允许我显示不同的颜色以及超链接和表情符号
我需要什么:
- 目前的自动换行行为以防万一,但仅在长字符串未用空格分隔以防止面板扩展的情况下才换行。
- 通过在输入区域中按 ENTER 或我将预先格式化的文本复制到输入面板中手动添加换行
- HTML 格式就像我已经拥有的一样
我尝试过的和没有帮助的:
jtextpane doesn't wrap text 和 JTextPane is not wrapping text
这里有一些代码可以自己尝试。左下角是一个输入区域,用于输入一些文本。您还可以通过按 Enter 来添加换行。点击按钮后,您将在上方区域看到文字。
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.IOException;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.border.TitledBorder;
import javax.swing.text.BadLocationException;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.StyleSheet;
@SuppressWarnings("serial")
public class LineWrapTest extends JFrame implements ActionListener, KeyListener {
private JButton btnSend;
private JTextArea textAreaIn;
private JEditorPane textAreaOut;
private HTMLEditorKit kit;
private HTMLDocument doc;
public LineWrapTest() {
this.setSize(600, 500);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setTitle("Linewrap Test");
}
/**
* Not important for problem
*/
public void paintScreen() {
this.setLayout(new BorderLayout());
this.add(this.getPanelOut(), BorderLayout.CENTER);
this.add(this.getPanelIn(), BorderLayout.SOUTH);
this.textAreaIn.requestFocusInWindow();
this.setVisible(true);
}
/**
* Not important for problem
*
* @return panelOut
*/
private JPanel getPanelOut() {
JPanel panelOut = new JPanel();
panelOut.setLayout(new BorderLayout());
this.textAreaOut = new JEditorPane();
this.textAreaOut.setEditable(false);
this.textAreaOut.setContentType("text/html");
this.kit = new HTMLEditorKit();
this.doc = new HTMLDocument();
StyleSheet styleSheet = this.kit.getStyleSheet();
this.kit.setStyleSheet(styleSheet);
this.textAreaOut.setEditorKit(this.kit);
this.textAreaOut.setDocument(this.doc);
TitledBorder border = BorderFactory.createTitledBorder("Output");
border.setTitleJustification(TitledBorder.CENTER);
panelOut.setBorder(border);
panelOut.add(this.textAreaOut);
return panelOut;
}
/**
* Not important for problem
*
* @return panelIn
*/
private JPanel getPanelIn() {
JPanel panelIn = new JPanel();
panelIn.setLayout(new BorderLayout());
this.textAreaIn = new JTextArea();
this.textAreaIn.setLineWrap(true);
this.textAreaIn.setWrapStyleWord(true);
TitledBorder border = BorderFactory.createTitledBorder("Input");
border.setTitleJustification(TitledBorder.CENTER);
panelIn.setBorder(border);
panelIn.add(this.getBtnSend(), BorderLayout.EAST);
panelIn.add(this.textAreaIn, BorderLayout.CENTER);
return panelIn;
}
/**
* Not important for problem
*
* @return btnSend
*/
private JButton getBtnSend() {
this.btnSend = new JButton("Send");
this.btnSend.addActionListener(this);
return this.btnSend;
}
private void append(String text) {
try {
this.kit.insertHTML(this.doc, this.doc.getLength(), text, 0, 0, null);
} catch (BadLocationException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private String getHTMLText() {
String txtIn = this.textAreaIn.getText().trim().replaceAll(SEPARATOR, "<br/>");
StringBuffer htmlBuilder = new StringBuffer();
htmlBuilder.append("<HTML>");
htmlBuilder.append(txtIn);
htmlBuilder.append("</HTML>");
return htmlBuilder.toString();
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == this.btnSend) {
this.append(this.getHTMLText());
this.textAreaIn.setText("");
this.textAreaIn.requestFocusInWindow();
}
}
public static void main(String[] args) {
LineWrapTest test = new LineWrapTest();
test.paintScreen();
}
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER)
if (!this.textAreaIn.getText().trim().isEmpty())
this.textAreaIn.setText(this.textAreaIn.getText() + SEPARATOR);
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
}
}
更新: 基于http://java-sl.com/tip_java7_text_wrapping_bug_fix.html的某些部分
不知何故,我想办法离我的目标更近了一点。我尝试将 HTMLEditorKit 的修复与 StlyedEditorKit 修复结合起来。但老实说,我不知道我在那里实际做了什么 :( 可悲的是,手动换行不再适用于此作为 HTMLEditorKit 的替代品。 或许您可以以此为基础进行更好的实现。
要在我的示例中使用它,只需在项目中使用 CustomEditorKit 创建一个新类,并将示例中的 HTMLEditorKit 替换为此 CustomEditorKit。 您会注意到现在可以使用单词和字母换行,但是如果您按 ENTER 来获得自己的换行,则此更改将不再出现在输出面板中,并且所有内容都将显示在一行中。 另一个奇怪的问题是,如果你调整框架的大小,线条有时会相互重叠。
import javax.swing.SizeRequirements;
import javax.swing.text.Element;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.InlineView;
import javax.swing.text.html.ParagraphView;
@SuppressWarnings("serial")
public class CustomEditorKit extends HTMLEditorKit {
@Override
public ViewFactory getViewFactory() {
return new HTMLFactory() {
@Override
public View create(Element e) {
View v = super.create(e);
if (v instanceof InlineView) {
return new InlineView(e) {
@Override
public int getBreakWeight(int axis, float pos, float len) {
return GoodBreakWeight;
}
@Override
public View breakView(int axis, int p0, float pos, float len) {
if (axis == View.X_AXIS) {
this.checkPainter();
this.removeUpdate(null, null, null);
}
return super.breakView(axis, p0, pos, len);
}
};
}
else if (v instanceof ParagraphView) {
return new ParagraphView(e) {
@Override
protected SizeRequirements calculateMinorAxisRequirements(int axis, SizeRequirements r) {
if (r == null) {
r = new SizeRequirements();
}
float pref = this.layoutPool.getPreferredSpan(axis);
float min = this.layoutPool.getMinimumSpan(axis);
// Don't include insets, Box.getXXXSpan will include them.
r.minimum = (int) min;
r.preferred = Math.max(r.minimum, (int) pref);
r.maximum = Integer.MAX_VALUE;
r.alignment = 0.5f;
return r;
}
};
}
return v;
}
};
}
}
【问题讨论】:
-
好的,以上代码对我来说就是这样。 JTextArea 完美包装。长字符串和单词都换行到下一行。 JEditorPane 会包装单词,直到它被一个长字符串扩展。然后换行,句子必须比扩展组件的字符串长。使用通用行分隔符,目前按 Enter 不会导致自定义换行。你想要什么:为长字符串包装 JEditorPane,不添加空格,就像 JTextArea 一样,这样它就不会被扩展。此外,通过在 JEpane 中输入自定义包装。
标签: java swing jeditorpane dom word-wrap