Search code examples
javaswingjscrollpanejtextpane

Java Simple Chat Box


I am trying to create a very simple chat window that simply has the ability to display some text, which I add to from time to time. However I get the following run time error when attempting to append text to the window:

java.lang.ClassCastException: javax.swing.JViewport cannot be cast to javax.swing.JTextPane
    at ChatBox.getTextPane(ChatBox.java:41)
    at ChatBox.getDocument(ChatBox.java:45)
    at ChatBox.addMessage(ChatBox.java:50)
    at ImageTest2.main(ImageTest2.java:160)

Here is the class to handle the basic operations:

public class ChatBox extends JScrollPane {

private Style style;

public ChatBox() {

    StyleContext context = new StyleContext();
    StyledDocument document = new DefaultStyledDocument(context);

    style = context.getStyle(StyleContext.DEFAULT_STYLE);
    StyleConstants.setAlignment(style, StyleConstants.ALIGN_LEFT);
    StyleConstants.setFontSize(style, 14);
    StyleConstants.setSpaceAbove(style, 4);
    StyleConstants.setSpaceBelow(style, 4);

    JTextPane textPane = new JTextPane(document);
    textPane.setEditable(false);

    this.add(textPane);
}

public JTextPane getTextPane() {
    return (JTextPane) this.getComponent(0);
}

public StyledDocument getDocument() {
    return (StyledDocument) getTextPane().getStyledDocument();
}

public void addMessage(String speaker, String message) {
    String combinedMessage = speaker + ": " + message;
    StyledDocument document = getDocument();

    try {
        document.insertString(document.getLength(), combinedMessage, style);
    } catch (BadLocationException badLocationException) {
        System.err.println("Oops");
    }
}
}

If there is a simpler way to do this, by all means let me know. I only need the text to be of a single font type, and uneditable by the user. Aside from that, I just need to be able to append text on the fly.


Solution

  • You have two options:

    1. Store the JTextPane in a member variable and return that inside getTextPane().
    2. Modify getTextPane to return the JViewPort's view, like this

      return (JTextPane) getViewport().getView();
      

    See the Swing tutorials for more detail.

    Also, as camickr (and the tutorials) pointed out, using add with a JScrollPane is incorrect. You should be either passing the component to the constructor or using setViewportView.

    As a side note, I try not to subclass Swing components unless it's absolutely necessary (preferring composition over inheritance). But that's not particularly relevant to the question.