Power to Build

Home » Misc » Gotcha: Java JScrollPane

Gotcha: Java JScrollPane

So, you are working with Swing. You build a small window with a Text box (JTextArea or JTextPane) like listed here. Everything works fine. You show text nicely wrapped in the text box.

Suddenly one day, the text pasted on to the Text box is longer than what’s in the view (View port). Sure, you say, I have seen this in other platforms. Just scroll, right?. Wait, there is no Scroll bar. Oops! Can you scroll with a up/down arrow key like in Windows? Nope! No luck! If you are coming from other IDE environment like me (PowerBuilder, Visual Studio – VB6/VB.Net or even C#) this will be a shocker.

In PowerBuilder, I would slap on Multi-line Edit on to a Window. Check the checkboxes for turning on Horizontal and Vertical Scrollbars. Set the text into the box. Bingo!

In PB and other such platforms, you don’t normally see the scrollbars, but the
Scrollbars appear magically, when the text is longer than the viewport, if you opted for it. You can also set Autoscroll instead of scrollbars, where user can scroll endlessly using the arrow key,until the memory runs out.

For e.g.,

In PowerBuilder, the code will look like this:

type mle_1 from multilineedit within w_sheet
 ....
 ....
 boolean init_hscrollbar = true
 boolean init_vscrollbar = true

end type

In C#, the scrollbars are added by default. If you want only Vertical bar only, you can set it like this:

      this.richTextBox1.ScrollBars =
             System.Windows.Forms.RichTextBoxScrollBars.Vertical;

This wraps text in the text box horizontally.

As you can see, scrollbars are just properties of the Text box cotrol. But then all the languages I mentioned are tightly coupled with the OS and the OS API has a lot of System functions that can be called as seen in C# code above.

None of those here in Java. Java tries to be everything for everyone. It has to mimic a lot OS level functions within, so it can run anywhere. In Java (here Swing) everything is available, but you have to go get it.Often times, you get a lot of options available to do the same thing, you have to find and use the right solution for you. And the Java solution is always like, if I can do this for this object, can I also do it for that other object? Thus, they try to extract the Scrolling functionality on its own and make it available for any component like Text box, or a JTable. You can even embed a pane (JPanel) onto a Scroll Pane. This approach of “decorating” any Visual object with Scroll Pane follows the Decorator Pattern. Here is a nice course material explaining how this is done.

Let’s see how the scrollbars can be added to a text box in Java:

To create a window, you create a JFrame or some kind of container (Equivalent to a Window in Windows environment). You plop a JPanel on to it, so you can contain all the controls together. Then you add a JTextArea on to the JPanel for your text box.

Wait, did you want scrolling capability? That’s a different pane; just add a JScrollPane to the JPanel, then add the JTextArea inside the JScrollPane. It is very hierarchical and very Object oriented. You can easily replace JTextArea with a Jtable or Jpanel to get scrollbar capability elsewhere.

Now, for the Gotcha part. Did I say, add the JTextArea to the JScrollPane? Wrong thing to do. This is what you do, typically add a component to a container/component using add method, but not so with JScrollPane. Here is why:

JScrollPane has a component called “View Port” already added to it. We can show a single component inside this “View Port”. So, essentially you will have to put the JTextArea in the View. Here is a diagram that may help you:

JScrollPane-1.gif

To do this in a Java way, you simply pass your component to the Constructor of JScrollPane. If you didn’t, then you will have to set the component to the View Port using, you guessed it,

scrollPane.setViewPortView(component)

or you can do it round about using

scrollPane.getViewPort.SetView(component)

But then, you have surely seen an add method in the Javadocs for JScrollPane?! Sure, it does have one, as it inherited it from JContainer. Like I said, JScrollPane already has a component inside it – that’s the ViewPort component. So, if you use the add method, you are replacing the Viewport with your component. That’s why if you added your component directly (by mistake) to the JScrollPane, your view port is gone and it will be grayed out.

So, here is the finished Java sample for a Text box with (only) Vertical Scrollbar:

import java.awt.*;
import javax.swing.*;

public class TextWithScrollbars
{
   public static void main(String[] args)
   {
      JFrame frame = new JFrame();
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setSize(400, 600);

      JTextArea area = new JTextArea(40, 60); // 40 rows, 60 columns
      JScrollPane scrollPane = new JScrollPane(area);
      scrollPane.setHorizontalScrollBar(null);

      Container contentPane = frame.getContentPane();
      contentPane.add(scrollPane, BorderLayout.CENTER);

      frame.setVisible(true);
   }
}

The line that reads,

scrollPane.setHorizontalScrollBar(null);

turns off the HorizontalScrollBar by setting it to Null. Otherwise, you would see that as well. Without horizontal scroll bar, it will automatically wrap text within the View port.


Comments, please?

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

%d bloggers like this: