我正在尝试使用JScrollPane和JTextArea实现滚动条。JTextArea一直被添加,我希望JScrollPane在添加更多文本时保持向下滚动。如何实现呢?
我正在尝试使用JScrollPane和JTextArea实现滚动条。JTextArea一直被添加,我希望JScrollPane在添加更多文本时保持向下滚动。如何实现呢?
如果您正在寻找(我认为是)更简单的答案,请查看:文本区滚动。
在JDK5之前,您需要在每次附加后手动更改插入符号的位置。现在,您可以像这样将此行为作为默认行为:
JTextArea textArea = new JTextArea(); DefaultCaret caret = (DefaultCaret)textArea.getCaret(); caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
这样做的好处是你不需要在代码中多次使用此片段!
scrollPane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
e.getAdjustable().setValue(e.getAdjustable().getMaximum());
}
});
如果您不断地向其中写入数据,则可以使用以下方法:
textArea.setCaretPosition(textArea.getDocument().getLength());
在添加新数据后,就会自动滚动到JScrollPane的底部。
这是解决方案。
JTextArea textArea = new JTextArea();
DefaultCaret caret = (DefaultCaret)textArea.getCaret();
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);`
jTextArea.setEditable(false)
。由Krigath建议的解决方案更通用,但在此处提问时存在问题JScrollPane and JList auto scroll。使用该问题的答案,您可以获得通用解决方案,例如: JScrollPane scrollPane = new JScrollPane(jTextArea);
verticalScrollBarMaximumValue = scrollPane.getVerticalScrollBar().getMaximum();
scrollPane.getVerticalScrollBar().addAdjustmentListener(
e -> {
if ((verticalScrollBarMaximumValue - e.getAdjustable().getMaximum()) == 0)
return;
e.getAdjustable().setValue(e.getAdjustable().getMaximum());
verticalScrollBarMaximumValue = scrollPane.getVerticalScrollBar().getMaximum();
});
如果您要在多线程程序中使用自动滚动,请小心。 例如,如果某个方法如下:
public void addNewLine(String s){
textPane.setText(textPane.getText()+"\n"+s);
if(autoscrollCheckBox.isSelected()){
this.revalidate();
JScrollBar vertical = scrollPane.getVerticalScrollBar();
vertical.setValue(vertical.getMaximum());
}
}
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at javax.swing.text.BoxView.calculateMajorAxisRequirements(BoxView.java:871)
at javax.swing.text.BoxView.checkRequests(BoxView.java:930)
at javax.swing.text.BoxView.getMinimumSpan(BoxView.java:568)
...
public void addNewLine(String s){
SwingUtilities.invokeLater( () -> {
textPaneOutput.setText(textPaneOutput.getText()+"\n"+s);
if(autoscrollCheckBox.isSelected()){
this.revalidate();
JScrollBar vertical = scrollPane.getVerticalScrollBar();
vertical.setValue(vertical.getMaximum());
}
});
}
这样你就能够自动滚动线程安全了!
我看了一下答案,发现@user9999的answer是一个适合那些想要滚动条持续滚动的好解决方案。我编辑了代码,去掉了变量。这使得当用户手动滚动时,滚动停止。如果用户滚动到文本区域或滚动区域的末尾,自动滚动会继续。
(正如@user9999建议的那样,我删除了变量,并添加了jScrollPane1.getHeight()
作为测量值,以便在当前滚动条值低于最大值时停止滚动)
以下是解决方法:
jScrollPane1.getVerticalScrollBar().addAdjustmentListener(
e -> {
if ((e.getAdjustable().getValue() - e.getAdjustable().getMaximum()) > -jScrollPane1.getHeight() - 20){
e.getAdjustable().setValue(e.getAdjustable().getMaximum());
}
});
-jScrollPane1.getHeight() - 20
中添加了-20
,因为有时候没有它就无法滚动,我猜-20
可以根据文本区域的字体大小进行调整。
setUpdatePolicy()
API解释得非常清楚。我已经相应地更新了我在引用问题中的答案。 - trashgod