在不向上滚动的情况下将文本前置到JTextArea(java swing)

在不向上滚动的情况下将文本前置到JTextArea(java swing),java,swing,jtextarea,Java,Swing,Jtextarea,如果我想在向末尾添加文本时防止JTextArea滚动到底部,那么解决方案非常简单:只需将插入符号的更新策略设置为DefaultCaret.NEVER_update,然后再调用JTextArea的append方法。我正在尝试做同样的事情(加载文本而不滚动),但用于预加文本而不是追加文本 我试过很多东西。其中一个是这样的,但它不起作用: public void loadMoreUp(){ caret = (DefaultCaret)ta.getCaret(); // ta is a JTex

如果我想在向末尾添加文本时防止JTextArea滚动到底部,那么解决方案非常简单:只需将插入符号的更新策略设置为DefaultCaret.NEVER_update,然后再调用JTextArea的append方法。我正在尝试做同样的事情(加载文本而不滚动),但用于预加文本而不是追加文本

我试过很多东西。其中一个是这样的,但它不起作用:

public void loadMoreUp(){
    caret = (DefaultCaret)ta.getCaret(); // ta is a JTextArea
    caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE); //doesn't work
    String s = "The new text\n";

    ta.setText(s + ta.getText()); // I have also tried with ta.getDocument().insertString(0,s,null)
}
我想要的行为是“新文本”被预先添加到顶部,但JTextArea不会随之向上滚动。除非用户手动向上滚动查看,“新文本”不应可见


如何将文本前置到JTextArea的顶部,而不向上滚动?如果相关的话,我的JTextArea在JScrollPane中。

因此,使您的
JTextArea
不可编辑是保持滚动条在顶部的原因。我不认为预先结束的文本会移动它,更重要的是它根本不会移动

但是,如果目标只是让滚动条沿着滚动窗格一直滚动,那么您真正需要做的就是设置插入符号的位置,没有人会更聪明

您甚至可以通过保存.getCaretPosition()并在以后使用该值,将插入符号位置设置为以前的某个位置

textArea.insert("Mein Hund frisst Nuesse\n", 0);
textArea.setCaretPosition(textArea.getDocument().getLength());
您可以在这里看到我的完整示例,您可以使用它来协调您的实现

import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import java.awt.Dimension;
import javax.swing.JButton;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Foo extends JFrame implements ActionListener
{
  JTextArea textArea;
  JScrollPane scrollPane;
  JButton button;

  public Foo()
  {
    textArea = new JTextArea();
    textArea.setEditable(false);
    textArea.setText("a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\np\nq\nr\ns\nt\nu\nv\nw\nx\ny\nz\n");
    scrollPane = new JScrollPane(textArea);
    scrollPane.setPreferredSize(new Dimension(400, 200));

    button = new JButton("Prepend");
    button.addActionListener(this);

    this.add(button, BorderLayout.PAGE_END);
    this.add(scrollPane, BorderLayout.PAGE_START);
  }

  public void actionPerformed(ActionEvent e)
  {
    if(e.getSource() == button)
    {
      textArea.insert("Mein Hund frisst Nuesse\n", 0);
      textArea.setCaretPosition(textArea.getDocument().getLength());
      //textArea.setText("Mein Hund frisst Nuesse\n" + textArea.getText());
    }
  }

  public static void main(String[] args)
  {
    Foo f = new Foo();
    f.setPreferredSize(new Dimension(500, 300));
    f.pack();
    f.setVisible(true);
  }
}

以下代码似乎有效:

public void loadMoreUp(){
    caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
    String s = "The new text\n";
    JScrollBar vbar = scrollPane.getVerticalScrollBar();
    int diff = vbar.getMaximum() - vbar.getValue();
    try{
        ta.getDocument().insertString(0, s, null);
    }
    catch(BadLocationException e){
        logger.error("Bad Location");
    }
    SwingUtilities.invokeLater(new Runnable(){
        public void run(){
            vbar.setValue(vbar.getMaximum()-diff);
        }
    });
}
基本思想是记住相对于文档结尾的位置(vbar.getMaximum()-vbar.getValue()),然后在预结束文本后恢复此值


需要invokeLater,否则getMaximum会在其值更新之前运行。此方法的缺点是invokeLater会使文本短暂闪烁。

我无法使用以下任一行代码复制此结果:
textArea.insert(“Mein Hund frisst Nuesse\n”,0)
textArea.setText(“Mein Hund frist Nuesse\n”+textArea.getText())我试图通过键入字母,然后再键入,直到我超过文本区域的大小,并得到滚动条来显示。然后我单击一个运行该代码的按钮,视口保持不变,显示我键入的最后几个字母。要查看前面的文本,我必须手动向上滚动。发布您的演示,演示您正在尝试执行的操作以及由此产生的问题。1). 不要使用setText()。2) 一定要使用Document.insertString(…)。@MarsAtomic My textArea的可编辑设置为false-这可能会有所不同吗?我所做的是滚动到一个大文本区域的中间,然后右键单击一个运行代码的按钮。当我点击按钮时,所有的东西都向下移动了一行。我正试图找到最简单的方法,使它不会改变。