Login | Register   
LinkedIn
Google+
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


Tip of the Day
Language: AWT
Expertise: Beginner
Apr 5, 1999

Repositioning Viewable Text in TextArea

Question:
Can I make the text in a TextArea scroll to a given line? For example, I have 100 lines of text in a TextArea with 20 viewable rows. Can I scroll the text (without manipulating the scrollbars physically) so that lines 70-90 are displayed in the TextArea?

Answer:
This is an excellent example of where you should use the Swing classes because of their enhanced functionality. With the regular AWT classes, it is almost impossible to scroll a TextArea automatically. To do so requires getting a reference to the TextArea's scrollbar and changing its value with setValue() or setValues(). But there is no way to get a reference to the scrollbar. There may be some intricate trickery you can go through to reach the desired result, but I cannot immediately see it.

Life is much simpler if you use JTextArea. Rather, I should say it is possible to do many more things with JTextArea. The Swing classes are powerful and often simple to use, but also have some idiosyncracies that can entail greater complexity. JTextArea stores its text as a linear sequence of characters, indexed by a single offset. This makes it difficult to reference its contents on a row and column basis. You can, however, query the begin and end offsets of each line of text with getLineStartOffset and getLineEndOffset. Once you obtain a location offset, you have to convert it to a view coordinate to scroll down to that position.

Unlike TextArea, JTextArea does not have a built-in set of scrollbars. None of the Swing classes do. To create a scrollable component, you have to add it to a JScrollPane. Each component stores a model of its contents that it converts to a coordinate that can be used by the scroll view to position and draw the scrolling area. For JTextArea, that model implements the javax.swing.text.Document interface. The class in charge of rendering the component subclasses javax.swing.text.View. These classes need not always be accessed directly because JTextArea contains convenience methods such as modelToView and the already mentioned getLineStartOffset. The modelToView method will convert a document offset into a view coordinate. Now you have all the pieces necessary to scroll the JTextArea automatically.

Once you obtain a view coordinate, all you have to do is tell the ScrollPane viewport to move to a new position by calling setViewPosition. The following code listing demonstrates how to make a JTextArea scroll to an arbitrary row. The only tricky part is to remember that a component already must be painted before you call setViewPosition.

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

public final class ScrollText extends JFrame {
  public static final int FIRST_VISIBLE_ROW = 69;

  private JTextArea __textArea;
  private JScrollPane __scrollPane;

  public ScrollText() {
    super("Scroll Text Demo");
    Container contentPane;

    __textArea = new JTextArea();
    __textArea.setColumns(40);
    __textArea.setRows(20);

    for(int row=1; row < 100; row++)
      __textArea.append(Integer.toString(row) + "\n");

    __scrollPane = new JScrollPane();
    __scrollPane.getViewport().add(__textArea);

    contentPane = getContentPane();
    
    contentPane.setLayout(new BorderLayout());

    contentPane.add(__scrollPane, BorderLayout.CENTER);
  }


  public void scrollToRow(int row) {
    int offset;
    JViewport viewport;
    Rectangle startLocation;

    viewport = __scrollPane.getViewport();

    try {
      offset =
	__textArea.getLineStartOffset(FIRST_VISIBLE_ROW);
      startLocation = __textArea.modelToView(offset);
      viewport.setViewPosition(new Point(startLocation.x, startLocation.y));
    } catch(BadLocationException e) {
    }
  }

  public static void main(String[] args) {
    final ScrollText demo;
    WindowListener exitListener;

    exitListener = new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
	Window window = e.getWindow();
	window.setVisible(false);
	window.dispose();
	System.exit(0);
      }
    };

    demo = new ScrollText();
    demo.addWindowListener(exitListener);
    demo.pack();
    demo.setVisible(true);
    // We have to make sure the JTextArea is painted before
    // changing the viewport position.  Otherwise modelToView()
    // will return null (see source to JTextComponent and
    // javax.swing.plaf.basic.BasicTextUI).  Calling setVisible does
    // not guarantee that the window will be painted before
    // scrollToRow() is called.
    Dimension size = demo.getSize();
    ((JComponent)(demo.getContentPane())).paintImmediately(
				   0, 0, size.width, size.height);
    demo.scrollToRow(FIRST_VISIBLE_ROW);

  }
}
DevX Pro
 
Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap
Thanks for your registration, follow us on our social networks to keep up-to-date