好!因此,我终于得到了您工作中遇到的所有问题。经过了一些研究和大量的反复试验,但是这里是:
这是我所做的:
- 将JEditorPane放在JScrollPane中,以便在消息变大时可以上下滚动
- 添加了自定义自动换行。自定义自动换行会将单词和长单词包装在所需的单词位置。您说对了,这是当前Java版本的错误。http://bugs.sun.com/view_bug.do?bug_id=7125737
- 通过单击Enter,使用户可以换行。但是,这会干扰自定义自动换行,因此您可能不喜欢我的实现方式。在代码示例中,我建议其他选项。
- 保留您的HTMLdocument功能。我很想不这样做,但是我发现周围的环境可以保留它。
- 该应用程序仍使用JEditorPane,但如果需要,可以将其切换为JTextPane。我都尝试过,它们都起作用。
所以这是代码。它有点长,您可能希望根据自己的喜好进行更改。我评论了所做的更改,并试图解释它们。
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.JScrollPane;import javax.swing.Jtextarea;import javax.swing.KeyStroke;import javax.swing.SizeRequirements;import javax.swing.border.TitledBorder;import javax.swing.text.*;import javax.swing.text.html.HTMLdocument;import javax.swing.text.html.HTMLEditorKit;import javax.swing.text.html.InlineView;import javax.swing.text.html.StyleSheet;@SuppressWarnings("serial")public class LineWrapTest extends Jframe implements ActionListener, KeyListener { //This is the separator. private String SEPARATOR = System.getProperty("line.separator"); private JButton btnSend; private Jtextarea textareaIn; private JEditorPane textareaOut; private JScrollPane outputScrollPane; private HTMLEditorKit kit; private HTMLdocument doc; public LineWrapTest() { this.setSize(600, 500); this.setDefaultCloseOperation(EXIT_ON_CLOSE); this.setLocationRelativeTo(null); this.setTitle("Linewrap Test"); } 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); } private JPanel getPanelOut() { JPanel panelOut = new JPanel(); panelOut.setLayout(new BorderLayout()); this.textareaOut = new JEditorPane(); this.textareaOut.setEditable(false); this.textareaOut.setContentType("text/html"); //I added this scroll pane. this.outputScrollPane = new JScrollPane(this.textareaOut); this.kit = new HTMLEditorKit(){@Override public ViewFactory getViewFactory(){ return new HTMLFactory(){ public View create(Element e){ View v = super.create(e); if(v instanceof InlineView){ return new InlineView(e){ public int getBreakWeight(int axis, float pos, float len) { //return GoodBreakWeight; if (axis == View.X_AXIS) { checkPainter(); int p0 = getStartOffset(); int p1 = getGlyphPainter().getBoundedPosition(this, p0, pos, len); if (p1 == p0) { // can't even fit a single character return View.BadBreakWeight; } try { //if the view contains line break char return forced break if (getdocument().getText(p0, p1 - p0).indexOf(SEPARATOR) >= 0) { return View.ForcedBreakWeight; } } catch (BadLocationException ex) { //should never happen } } return super.getBreakWeight(axis, pos, len); } public View breakView(int axis, int p0, float pos, float len) { if (axis == View.X_AXIS) { checkPainter(); int p1 = getGlyphPainter().getBoundedPosition(this, p0, pos, len); try { //if the view contains line break char break the view int index = getdocument().getText(p0, p1 - p0).indexOf(SEPARATOR); if (index >= 0) { GlyphView v = (GlyphView) createFragment(p0, p0 + index + 1); return v; } } catch (BadLocationException ex) { //should never happen } } return super.breakView(axis, p0, pos, len); } }; } else if (v instanceof ParagraphView) { return new ParagraphView(e) { protected SizeRequirements calculateMinorAxisRequirements(int axis, SizeRequirements r) { if (r == null) { r = new SizeRequirements(); } float pref = layoutPool.getPreferredSpan(axis); float min = 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; } }; } }; 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); //I changed this to add the scrollpane, which now contains //the JEditorPane panelOut.add(this.outputScrollPane); return panelOut; } private JPanel getPanelIn() { JPanel panelIn = new JPanel(); panelIn.setLayout(new BorderLayout()); this.textareaIn = new Jtextarea(); this.textareaIn.setLineWrap(true); this.textareaIn.setWrapStyleWord(true); //This disables enter from going to a new line. Your key listener does that. this.textareaIn.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "none"); //For the key listener to work, it needs to be added to the component this.textareaIn.addKeyListener(this); 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; } 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() { //I tried to find a work around for this but I couldn't. It could be done //by manipulating the HTMLdocument but it's beyond me. Notice I changed //<br/> to <p/>. For some reason, <br/> no longer went to the next line //when I added the custom wrap. <p/> seems to work though. String txtIn = this.textareaIn.getText().trim().replaceAll(SEPARATOR, "<p/>"); //My IDE recommends you use StringBuilder instead, that's up to you. //I am not sure what the difference would be. 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()) { //I made this work by defining the SEPARATOR. //You could use append(Separator) instead if you want. this.textareaIn.setText(this.textareaIn.getText() + SEPARATOR); } } } @Override public void keyReleased(KeyEvent e) { } @Override public void keyTyped(KeyEvent e) { }}这里是(大多数)我用来解决此问题的链接:
使用HTMLdocument在JTextPane中启用自动换行
自定义换行是以下两者的组合:
http://java-sl.com/tip_html_letter_wrap.html
http://java-sl.com/wrap.html
删除Jtextarea的keybind:
http://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html
如果您有任何疑问,请在下面评论。 我会回答他们。我衷心希望这能解决您的问题



