Java Tips Weblog

  • Blog Stats

    • 1,097,373 hits
  • Categories

  • Archives

No Wrap Text Pane

Posted by Rob Camick on January 25, 2009

By default a JTextPane wraps text when displayed in a scroll pane. Unlike a JTextArea there is no property to turn off wrapping. I have seen many different suggestions on how to turn off wrapping in a text pane. However, all the solutions I’ve seen have a common problem in that the caret is no longer visible at the right edge of the viewport as text is being entered.

Update: I have found a solution that does not have a problem with the caret visibility. You can skip to the bottom for this solution or continue reading.

Before addressing this problem, I’ll first suggest a simple solution to turn off wrapping in a text pane. The solution is to add the text pane to a JPanel using a BorderLayout and then add the panel to the scroll pane:

JTextPane textPane = new JTextPane();
JPanel noWrapPanel = new JPanel( new BorderLayout() );
noWrapPanel.add( textPane );
JScrollPane scrollPane = new JScrollPane( noWrapPanel );

The reason this solution works has to do with how the Scrollable interface is implemented. For a JTextPane the getScrollableTracksViewportWidth() method always returns “true”. This means that the width of the text pane is always assumed to be the width of the viewport which results in the text pane always wrapping the text to make sure it is visible in the viewport. However, a JPanel does not implement the Scrollable interface so the default behaviour of the scroll pane is used. In this case the component is displayed at its preferred width so lines of text will not be wrapped and a horizontal scollbar will appear when needed.

When using the above code you will notice that when the caret is placed after the “6″, it is painted exactly at the right edge of the viewport so the caret is not visible:

no-wrap-text-pane1

Now, to address the problem of Caret visibility you can use the VisibleCaretListener class. This class is simply a CaretListener that will attempt to scroll the viewport a few extra pixels every time the Caret is moved. The VisibleCaretListener is added to the text pane using the following line of code: 

textPane.addCaretListener(new VisibleCaretListener());

As you can see in the following image the caret is now visible after the “6″ because the viewport has been scrolled extra pixels by the VisibleCaretListener:

no-wrap-text-pane2

The default is to scroll 2 more pixels, which is enough to see the Caret. I choose this as the default since this is the way a text area appears to work. However, increasing the default value will allow you to see more of the text following the caret.

Although this class was initially written to solve the caret visibility when using a “no wrap” text pane it can also be used on a JTextArea to increase the number of visible pixels of text after the caret when the caret is at the right edge of the viewport.

Update November 6, 2011:

Scrolling is controlled by the implementation of the Scrollable interface. By overriding the getScrollableTracksViewportWidth() method we can achieve a non-wrapping text pane:

JTextPane textPane = new JTextPane()
{
    public boolean getScrollableTracksViewportWidth()
    {
        return getUI().getPreferredSize(this).width 
            <= getParent().getSize().width;
    }
};

This solution was found in Non Wrapping Text Pane

Another Update (March 27, 2013)

As noted by Sheridan in a comment below, caret visibility is an issue with this solution in JDK7. I originally tested the code in JDK6 and I’m 99% sure it worked correctly ;-) Maybe someone can confirm if it does or doesn’t work in JDK6 so I’ll know whether I was dreaming or not when I made the observation. Anyway, if you have problems with the caret visibility then I suggest you use the VisibleCaretListener with this code as well.

Get The Code

VisibleCaretListener.java

Related Reading

How to Write a Caret Listener
Java API: javax.swing.Scrollable

About these ads

21 Responses to “No Wrap Text Pane”

  1. Weslei said

    Thanks! This solved my problem!

  2. John Vasilopoulos said

    Great solution and easy to implement…thank you!!

  3. Mark said

    I love this! Can you tell me how to make it wrap with a panel in it? I added your line numberer to my JTextPane and I want it to wrap the lines. Please reply.

    • Rob Camick said

      Sorry, I don’t understand what you are asking. The point is this tip is to NOT wrap lines in a text pane.

      • Mark said

        Well, I am trying to add your line numberer to my textpane (which is in a scrollpane), but since the line numberer is a panel, it automatically doesn’t wrap the text. I want to know how to wrap the text with the line numberer panel in the scrollpane.

      • Rob Camick said

        My blog entry shows you how to use the TextLineNumber component. You don’t add it to a text pane, you add it to the scroll pane.

  4. Connor said

    Wow thank you so much! I’m 17, teaching myself Java, and this has been incredibly helpful! I’m making an IDE of sorts, and needed to format text but also not have it wrap.

    Thank you!

  5. Aubrey said

    Yeahhhhhhhhh, nice one – works like magic!

  6. Ravindu Kaluarachchi said

    This works,Thankyou! :)

  7. You rock man!

  8. Witcher said

    Thank you, simple solution, perfect. :)

  9. Sheridan Vespo said

    Hello Rob,

    I tried your solution with overloading the getScrollableTracksViewportWidth() function in the JTextPane, but I have caret visibility problems.
    Since you wrote “Update: I have found a solution that does not have a problem with the caret visibility. You can skip to the bottom for this solution or continue reading.”, I figured, that the solutino of November 6, 2011 would be the one without the problems.

    Did I misinterpret your line, and the only way to fix the caret visibility is the listener, or should this solution in fact not cause problems with the visibility and my error hence must be somewhere else?

    • Rob Camick said

      Hi Sheridan, you interpreted my posting correctly. The update should have fixed both problems. That comment was written when I was using JDK6. However, I just tested the code again (I’m now using JDK7_10) and the caret is indeed hidden. So I would suggest that you do also need to use the VisibleCaretListener. I don’t know if this is a difference between JDK6 and 7 or whether I was half sleeping when I made the original update ;-) Thanks for the feedback.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.

Join 88 other followers

%d bloggers like this: