Java7中的JEditorPane换行

Java7中的JEditorPane换行,java,swing,jeditorpane,dom,word-wrap,Java,Swing,Jeditorpane,Dom,Word Wrap,首先,我希望这不是一个问题,我开始了一个新的话题。Tbh我不知道如何根据已经回答的问题提问,所以我做了这个 我对Java非常陌生,我的问题如下。我正在编写一个小聊天程序,我正在使用JEditorPane和HTMLEditorKit来显示不同颜色的文本,显示笑脸和超链接 我的问题是,经过一些研究,我发现问题可能是由于Java7,我无法让换行器正常工作。我希望文本进行文字包装,并在超过组件宽度的字符串中间进行包装。 wrap这个词很好用,但是如果有人键入一个很长的字符串,JEditorPane会被展

首先,我希望这不是一个问题,我开始了一个新的话题。Tbh我不知道如何根据已经回答的问题提问,所以我做了这个

我对Java非常陌生,我的问题如下。我正在编写一个小聊天程序,我正在使用
JEditorPane
HTMLEditorKit
来显示不同颜色的文本,显示笑脸和超链接

我的问题是,经过一些研究,我发现问题可能是由于Java7,我无法让换行器正常工作。我希望文本进行文字包装,并在超过组件宽度的字符串中间进行包装。 wrap这个词很好用,但是如果有人键入一个很长的字符串,
JEditorPane
会被展开,你需要调整框架的大小,以获得屏幕上的所有内容,这是我不希望发生的事情

我已经尝试了一些解决这个问题的方法,但是它们只允许换行,这样换行就不能工作了。除此之外,我希望用户能够通过按Enter键包装文本。为此,我将\n添加到文本中,通过修复,这将不再影响结果,所有内容都将显示在一行中

我感觉自己花了很多年的时间在网络上寻找解决方案,但现在我的情况没有任何效果,特别是因为它似乎一直都是相同的解决方案。我希望你们能帮助我

总而言之,这意味着:

我所拥有的:

  • 如果长字符串由空格分隔,则换行
  • 如果使用Windows,并且输入包含通过按enter键创建的换行,则它们也将换行
  • 如果键入不带空格的很长字符串,面板将展开,需要调整框架的大小
  • HTML格式允许我显示不同的颜色以及超链接和表情
我需要什么:

  • 在可能的情况下,单词的换行行为与当前相同,但只有在长字符串没有空格分隔的情况下,字母才会换行,以防止面板膨胀
  • 通过在输入区域中按ENTER键或将预格式化文本复制到输入面板中,手动添加换行
  • HTML格式,就像我已经做过的一样
我尝试过的和没有帮助的:

这里有一些代码可以自己尝试。左下角是一个输入区域,用于输入一些文本。也可以通过按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) {
}
}

好的!所以,我终于得到了你在工作中遇到的所有问题。这需要一些研究和大量的尝试和错误,但这里是:

以下是我所做的:

  • 将JEditorPane放在JScrollPane中,以便在消息变大时可以上下滚动
  • 添加了自定义换行符。自定义换行符将在单词的所需位置换行单词和长单词。你是对的,这是Java当前版本的一个bug
  • 增加了用户通过按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");
    }

    /**
     * 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");

        //I added this scroll pane.
        this.outputScrollPane = new JScrollPane(this.textAreaOut);

        /*
         * This is a whole whack of code.  It's a combination of two sources.
         * It achieves the wrapping you desire: by word and longgg strings
         * It is a custom addition to HTMLEditorKit
         */
        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;
    }

    /**
     * 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);

        //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;
    }

    /**
     * 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() {
        //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) {
    }

}
导入java.awt.BorderLayout;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.event.KeyEvent;
导入java.awt.event.KeyListener;
导入java.io.IOException;
导入javax.swing.BorderFactory;
导入javax.swing.JButton;
导入javax.swing.JEditorPane;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.JScrollPane;
导入javax.swing.JTextArea;
导入javax.swing.KeyStroke;
导入javax.swing.SizeRequirements;
导入javax.swing.border.TitledBorder;
导入javax.swing.text.*;
导入javax.swing.text.html.HTMLDocument;
导入javax.swing.text.html.HTMLEditorKit;
导入javax.swing.text.html.InlineView;
导入javax.swing.text.html.StyleSheet;
@抑制警告(“串行”)
公共类LineWrapTest扩展JFrame实现ActionListener、KeyListener{
//这是分离器。
私有字符串分隔符=System.getProperty(“line.SEPARATOR”);
私人JButton btnSend;
私人JTextArea textAreaIn;
私人绝地武士;
私有JScrollPane输出滚动窗格;
私人HTMLeditor工具包;
私人HTMLDocument文件;
公共LineWrapTest(){
这个。设置大小(600500);
此.setDefaultCloseOperation(关闭时退出);
此.setLocationRelativeTo(空);
本文件为setTitle(“缠绕试验”);
}
/**
*这个问题不重要
*/
公共屏幕(){
此.setLayout(新的BorderLayout());
add(this.getPanelOut(),BorderLayout.CENTER);
add(this.getPanelIn(),BorderLayout.SOUTH);
此.textAreaIn.requestFocusInWindow();
此.setVisible(true);
}
/**
*这个问题不重要
* 
*@返回面板
*/
私有JPanel getPanelOut(){
JPanel panelOut=新的JPanel();
setLayout(新的BorderLayout());
this.textAreaOut=new JEditorPane();
this.textAreaOut.setEditable(false);
this.textAreaOut.setContentType(“text/html”);
//我添加了这个滚动窗格。
this.outputScrollPane=新的JScrollPane(this.textAreaOut);
/*
*这是一个完整的代码。它是两个源代码的组合。
*它达到了你想要的包装效果
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");
    }

    /**
     * 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");

        //I added this scroll pane.
        this.outputScrollPane = new JScrollPane(this.textAreaOut);

        /*
         * This is a whole whack of code.  It's a combination of two sources.
         * It achieves the wrapping you desire: by word and longgg strings
         * It is a custom addition to HTMLEditorKit
         */
        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;
    }

    /**
     * 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);

        //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;
    }

    /**
     * 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() {
        //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) {
    }

}
class WrapColumnFactory extends HTMLEditorKit.HTMLFactory {

        @Override
        public View create(Element elem) {
            View v = super.create(elem);

            if (v instanceof LabelView) {

                // the javax.swing.text.html.BRView (representing <br> tag) is a LabelView but must not be handled
                // by a WrapLabelView. As BRView is private, check the html tag from elem attribute
                Object o = elem.getAttributes().getAttribute(StyleConstants.NameAttribute);
                if ((o instanceof HTML.Tag) && o == HTML.Tag.BR) {
                    return v;
                }

                return new WrapLabelView(elem);
            }

            return v;
        }
    }

    class WrapLabelView extends LabelView {

        public WrapLabelView(Element elem) {
            super(elem);
        }

        @Override
        public float getMinimumSpan(int axis) {
            switch (axis) {
                case View.X_AXIS:
                    return 0;
                case View.Y_AXIS:
                    return super.getMinimumSpan(axis);
                default:
                    throw new IllegalArgumentException("Invalid axis: " + axis);
            }
        }

    }