Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>This is pieced together, untested, from the API documentation:</p> <ul> <li>use <code>getViewport()</code> on your <code>JScrollPane</code> to get a hold of the viewport.</li> <li>use <code>Viewport.getViewPosition()</code> to get the top-left coordinates. These are absolute, not a percentage of scrolled text.</li> <li>use <code>Viewport.addChangeListener()</code> to be notified when the top-left position changes (among other things). You may want to create a mechanism to distinguish user changes from changes your program makes, of course.</li> <li>use <code>Viewport.setViewPosition()</code> to set the top-left position to where it was before the disturbance.</li> </ul> <p><strong>Update:</strong></p> <ul> <li>To stop JTextArea from scrolling, you may want to override its <code>getScrollableTracksViewport{Height|Width}()</code> methods to return <code>false</code>.</li> </ul> <p><strong>Update 2:</strong></p> <p>The following code does what you want. It's amazing how much trouble I had to go to to get it to work:</p> <ul> <li>apparently the <code>setViewPosition</code> has to be postponed using <code>invokeLater</code> because if it's done too early the text update will come after it and nullify its effect.</li> <li>also, for some weird reason perhaps having to do with concurrency, I had to pass the correct value to my <code>Runnable</code> class in its constructor. I had been using the "global" instance of <code>orig</code> and that kept setting my position to 0,0.</li> </ul> <hr> <pre><code>public class Sami extends JFrame implements ActionListener { public static void main(String[] args) { (new Sami()).setVisible(true); } private JTextArea textArea; private JScrollPane scrollPane; private JButton moreTextButton = new JButton("More text!"); private StringBuffer text = new StringBuffer("0 Silly random text.\n"); private Point orig = new Point(0, 0); public Sami() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); getContentPane().setLayout(new BorderLayout()); this.textArea = new JTextArea() { @Override public boolean getScrollableTracksViewportHeight() { return false; } @Override public boolean getScrollableTracksViewportWidth() { return false; } }; this.scrollPane = new JScrollPane(this.textArea); getContentPane().add(this.scrollPane, BorderLayout.CENTER); this.moreTextButton.addActionListener(this); getContentPane().add(this.moreTextButton, BorderLayout.SOUTH); setSize(400, 300); } @Override public void actionPerformed(ActionEvent arg0) { int lineCount = this.text.toString().split("[\\r\\n]").length; this.text.append(lineCount + "The quick brown fox jumped over the lazy dog.\n"); Point orig = this.scrollPane.getViewport().getViewPosition(); // System.out.println("Orig: " + orig); this.textArea.setText(text.toString()); SwingUtilities.invokeLater(new LaterUpdater(orig)); } class LaterUpdater implements Runnable { private Point o; public LaterUpdater(Point o) { this.o = o; } public void run() { // System.out.println("Set to: " + o); Sami.this.scrollPane.getViewport().setViewPosition(o); } } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload