【问题标题】:Prepend text to JTextArea without scrolling up (java swing)在不向上滚动的情况下将文本添加到 JTextArea (java swing)
【发布时间】:2019-12-15 03:56:49
【问题描述】:

如果我想防止 JTextArea 在添加文本时滚动到底部,解决方案非常简单:只需在调用 JTextArea 的 append 方法之前将插入符号的更新策略设置为 DefaultCaret.NEVER_UPDATE 即可。我正在尝试做同样的事情(加载文本而不滚动),但用于添加文本而不是附加文本。

我尝试了很多东西。其中之一是这样,但它不起作用:

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 中。

【问题讨论】:

  • 我无法使用以下任一代码行来重现此问题:textArea.insert("Mein Hund frisst Nuesse\n", 0); textArea.setText("Mein Hund frisst Nuesse\n" + textArea.getText()); 我尝试通过键入字母后跟 进行重现,直到我通过了 textArea 的大小和让滚动条显示。然后我单击一个运行该代码的按钮,并且视口保持不变,显示我输入的最后一个字母。要查看前置文本,我必须手动向上滚动。
  • 发布您的minimal reproducible example,展示您正在尝试做的事情以及由此产生的问题。 1)。不要使用 setText()。 2) 使用 Document.insertString(...)。
  • @MarsAtomic 我的 textArea 已将 editable 设置为 false - 也许这会有所不同?我所做的是滚动到一个大文本区域的中间,然后右键单击一个运行代码的按钮。当我单击按钮时会发生什么,所有内容都会向下移动。我正在努力寻找最简单的方法让它不移动。

标签: java swing jtextarea


【解决方案1】:

所以事实证明,使您的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);
  }
}

【讨论】:

    【解决方案2】:

    以下代码似乎有效:

    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);
            }
        });
    }
    

    基本思想是记住相对于文档END的位置(vbar.getMaximum() - vbar.getValue()),然后在添加文本后恢复这个值。

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

    【讨论】:

      猜你喜欢
      • 2011-09-08
      • 2011-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多