Java / Swing:JScrollPane中的JTextArea,如何防止自动滚动?
这是一段可运行的代码,显示了我的“问题”是什么。
我有一个包裹在 JScrollPane
中的 JTextArea
。当我更改 JTextArea
的文本时,JScrollPane
自动滚动到文本末尾,但我不希望这样。
以下是我的要求:
- 应用程序不应该自动垂直滚动,但是...
- 用户应该能够垂直滚动
- 用户不应该能够水平滚动
- 应用程序不应该水平滚动
- JTextArea 不得可编辑
(因此,即使文本多于水平方向所能容纳的内容,应用程序和用户都不应该能够水平滚动。垂直,只有用户应该能够滚动。)
我不知道如何“修复”这个问题:应该使用 JTextArea
或 JScrollPane
方法修复这个问题吗?
请注意,AFAICT 这根本不是重复的:JTextPane 阻止在父级 JScrollPane 中滚动
这是有点有趣的例子,每 200 毫秒它就会在 JTextArea 中放入新文本,您可以看到 JScrollPane 总是自动滚动到文本末尾。
import javax.swing.*;
import java.awt.*;
import java.util.Random;
public final class TextInScrollPane extends JFrame {
private static final Random r = new Random( 42 );
public static void main( final String[] args ) {
final JFrame f = new JFrame();
f.setDefaultCloseOperation( EXIT_ON_CLOSE );
f.setLayout(new BorderLayout());
final JTextArea jta = new JTextArea( "Some text", 30, 30 );
jta.setEditable( false ); // This must not be editable
final JScrollPane jsp = new JScrollPane( jta );
jsp.setHorizontalScrollBarPolicy( JScrollPane.HORIZONTAL_SCROLLBAR_NEVER );
jsp.setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_ALWAYS );
f.add( jsp, BorderLayout.CENTER );
f.pack();
f.setLocationRelativeTo( null );
f.setVisible(true);
final Thread t = new Thread( new Runnable() {
public void run() {
while ( true ) {
try {Thread.sleep( 200 );} catch ( InterruptedException e ) {}
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < 50 + r.nextInt( 75 ); i++) {
for (int j = 0; j < r.nextInt(120); j++) {
sb.append( (char) 'a' + r.nextInt(26) );
}
sb.append( '\n' );
}
SwingUtilities.invokeLater( new Runnable() {
public void run() {
jta.setText( sb.toString() );
}
} );
}
}
});
t.start();
}
}
here's a runnable piece of code that shows what my "problem" is.
I've got a JTextArea
wrapped in a JScrollPane
. When I change the text of the JTextArea
, the JScrollPane
scrolls automatically to the end of the text and I don't want that.
Here are my requirements:
- the application should not scroll vertically automatically but...
- the user should be able to scroll vertically
- the user should not be able to scroll horizontally
- the application should never scroll horizontally
- the JTextArea must not be editable
(so even if there's more text than what can fit horizontally, neither the application nor the user should be able to scroll horizontally. While vertically, only the user should be able to scroll.)
I don't know how to "fix" this: should this be fixed using JTextArea
or JScrollPane
methods?
Note that AFAICT this is not a duplicate at all of: JTextPane prevents scrolling in the parent JScrollPane
Here's the kinda funny example, every 200 ms it puts new text in the JTextArea
and you can see the JScrollPane
always scrolling automatically to the end of the text.
import javax.swing.*;
import java.awt.*;
import java.util.Random;
public final class TextInScrollPane extends JFrame {
private static final Random r = new Random( 42 );
public static void main( final String[] args ) {
final JFrame f = new JFrame();
f.setDefaultCloseOperation( EXIT_ON_CLOSE );
f.setLayout(new BorderLayout());
final JTextArea jta = new JTextArea( "Some text", 30, 30 );
jta.setEditable( false ); // This must not be editable
final JScrollPane jsp = new JScrollPane( jta );
jsp.setHorizontalScrollBarPolicy( JScrollPane.HORIZONTAL_SCROLLBAR_NEVER );
jsp.setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_ALWAYS );
f.add( jsp, BorderLayout.CENTER );
f.pack();
f.setLocationRelativeTo( null );
f.setVisible(true);
final Thread t = new Thread( new Runnable() {
public void run() {
while ( true ) {
try {Thread.sleep( 200 );} catch ( InterruptedException e ) {}
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < 50 + r.nextInt( 75 ); i++) {
for (int j = 0; j < r.nextInt(120); j++) {
sb.append( (char) 'a' + r.nextInt(26) );
}
sb.append( '\n' );
}
SwingUtilities.invokeLater( new Runnable() {
public void run() {
jta.setText( sb.toString() );
}
} );
}
}
});
t.start();
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如何在Java GUI中设置JTextArea的自动滚动?
http:// /download.oracle.com/javase/1.5.0/docs/api/javax/swing/text/DefaultCaret.html#NEVER_UPDATE
尝试:
这应该可以防止插入符号自动使文档滚动到底部。
How to set AUTO-SCROLLING of JTextArea in Java GUI?
http://download.oracle.com/javase/1.5.0/docs/api/javax/swing/text/DefaultCaret.html#NEVER_UPDATE
Try:
This should prevent the caret from automatically making the document scroll to the bottom.
回答我自己的问题:我不太确定这是解决我的问题的最佳方法,但使用
setCaretPosition(0)
设置JTextArea's
插入符似乎工作正常:Answering my own question: I'm not exactly sure this is the best way to solve my issue, but setting the
JTextArea's
caret usingsetCaretPosition(0)
seems to work fine:您在 Document 类的实现中遇到了非常奇怪的行为。我在 JScrollPane 内的 JTextPane 中使用 DefaultStyledDocument。
现在,这是奇怪的事情。如果我更新 EventQueue 上的文档(就像您通过安排可运行程序稍后运行一样),滚动窗格会自动滚动到末尾。
然而,文档类声称是线程安全的并且实际上可以从另一个线程更新。如果我确保在 EventQueue 之外的另一个线程上进行更新,则一切正常,但滚动窗格不会滚动到末尾。
我没有解释为什么会这样,我没有查看 Swing 源代码。自 2006 年以来我一直在利用这个“功能”,到目前为止它一直是一致的:-)
You have run into a very strange behaviour in the implementation of the Document classes. I use a DefaultStyledDocument in a JTextPane inside a JScrollPane.
Now, here is the wierd thing. If I update the document on the EventQueue (like you do by scheduling a runnable to run later) the scroll pane automatically scrolls to the end.
However, the document classes claim to be thread safe and actually updatable from another thread. If I make sure to update on another thread than the EventQueue everything works fine but the scroll pane does NOT scroll to the end.
I have no explanation as to why this is so, I haven't looked in the Swing source. I have been exploiting this "feature" since 2006 and it has been consistent so far :-)