Search code examples
javaswingjscrollpanejtextarea

How do I get the cursor to the TOP of a JTextArea inside a JScrollPane


For a long time I've been living with the cursor being at the bottom of my JTextArea named txaOutput after being populated in a JScrollPane even though I WANT it positioned at the TOP.

Tthe only help I've found has referred to setting the caret position to 0 (e.g., txaOutput.setCaretPosition(0);), which I'd never figured out how to make work properly.

Today I just went through every conceivable method for JTextArea and finally found that, BEFORE populating it, this line seems to do what I need:

txaOutput.insert(" ", 1 );

SURELY this isn't the best or only way.

Here's the class for the text area:

package masterwords;
import gbl.GBConstraints;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagLayout;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;
import javax.swing.WindowConstants;

public class HelpOutput extends JFrame {

  private JScrollPane scrPnl;
  private JTextArea txaOutput;  

  public     HelpOutput() /* constructor */ {

    scrPnl = new JScrollPane();

    txaOutput    = new JTextArea();

    setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

    scrPnl.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
    scrPnl.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
    scrPnl.setViewportBorder(BorderFactory.createEtchedBorder());
    scrPnl.setAutoscrolls(false);
    scrPnl.setPreferredSize(new Dimension(500, 555));

    txaOutput.setFont(new Font("Courier New", 0, 14)); 
    scrPnl.setViewportView(txaOutput);

    setLayout(new GridBagLayout());

    add(scrPnl, new GBConstraints(0,0).ipad(200, 300).spanX(100).spanY(90));

    txaOutput.insert(" ", 1 );  // ********** WITHOUT THIS CURSOR IS AT BOTTOM
    setVisible(true);
    pack();
  }

  public void appendHelp(String s){
    txaOutput.append(s);
  }
}

Here's how I've always called it but it NEVER worked until adding line with ************ above:

  private void btnHelpActionPerformed (ActionEvent evt) {                                        

    HelpOutput helpOutput = new HelpOutput();

    Scanner sc = openHelp();
    while(sc.hasNext())
      helpOutput.appendHelp(sc.next());

   // txaOutput.setCaretPosition(0); // THIS DOES NOTHING so commented out!!!
  }   

Prior to adding the line with all the **************s, NOTHING ELSE I tried put the cursor at the TOP of the text area--always the bottom.

WHAT SHOULD I BE DOING? What I AM doing seems a kludge.

* EDIT, THANKS TO JAVANATOR *

Rename variable txaOutput to txaHelpOutput; problem solved. New key lines:

  private void btnHelpActionPerformed (ActionEvent evt) {                                        

    HelpOutput helpOutput = new HelpOutput();

    Scanner sc = openHelp();
    while(sc.hasNext())
      helpOutput.appendHelp(sc.next());

   txaHelpOutput.setCaretPosition(0);
   // ^^^^
  }   


public class HelpOutput extends JFrame {

  private JTextArea txaHelpOutput;  
  //                   ^^^^

  public     HelpOutput() /* constructor */ {

    txaHelpOutput    = new JTextArea();
    // ^^^^

    scrPnl.setViewportView(txaHelpOutput);
    //                        ^^^^

    // LOSE THIS LINE!! txaHelpOutput.insert(" ", 1 ); 
  }

Solution

  • First, txaOutput.insert(" ", 1 ); inserts a space into your help text, which is probably not what you want.

    Second, you create a HelpOutput object, append text to it, but then you call setCaretPosition on some other object referenced by txaOutput. You need to call setCaretPosition on the HelpOutput object's JTextArea. This is easily done by creating a method in HelpOutput which calls setCaretPosition(0).

    The following code will produce a text area with the carrot at the top, using setCaretPosition(0).

    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.Font;
    import java.awt.event.ActionEvent;
    
    import javax.swing.BorderFactory;
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    import javax.swing.ScrollPaneConstants;
    import javax.swing.SwingUtilities;
    import javax.swing.WindowConstants;
    
    public class HelpOutput extends JFrame
    {
        private static final long   serialVersionUID    = -1323914827861467580L;
        private JScrollPane         scrPnl;
        private JTextArea           txaOutput;
    
        public static void main(String[] args)
        {
            SwingUtilities.invokeLater(new Runnable()
            {
                @Override
                public void run()
                {
                    btnHelpActionPerformed(null);
                }
            });
        }
    
        public HelpOutput()
        {
    
            scrPnl = new JScrollPane();
            txaOutput = new JTextArea();
    
            setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
    
            scrPnl.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
            scrPnl.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
            scrPnl.setViewportBorder(BorderFactory.createEtchedBorder());
            scrPnl.setAutoscrolls(false);
            scrPnl.setPreferredSize(new Dimension(500, 555));
    
            txaOutput.setFont(new Font("Courier New", 0, 14));
            scrPnl.setViewportView(txaOutput);
    
            setLayout(new BorderLayout());
    
            add(scrPnl, BorderLayout.CENTER);
    
            setVisible(true);
            pack();
        }
    
        public void appendHelp(String s)
        {
            txaOutput.append(s);
        }
    
        public void putCarrotAtTop()
        {
            txaOutput.setCaretPosition(0);
        }
    
        private static void btnHelpActionPerformed(ActionEvent evt)
        {
            HelpOutput helpOutput = new HelpOutput();
    
            helpOutput
                    .appendHelp("Lots of help\nLots of help\nLots of help\nLots of help\nLots of help\n");
            helpOutput.putCarrotAtTop();
        }
    }