gpt4 book ai didi

java - 智能 JScrollPane 自动滚动

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:21:31 25 4
gpt4 key购买 nike

我正在尝试在包含 JTextPane 的 JScrollPane 上实现智能自动滚动。 JTextPane 用于以彩色记录我的应用程序。但是,我在尝试进行智能自动滚动时遇到了障碍。我所说的智能自动滚动并不是指每次发生变化时都盲目地自动滚动,我的意思是检查你是否一直向下滚动,然后自动滚动。然而,无论我做什么,要么总是自动滚动,要么根本不滚动

作为测试脚本,这里是设置(JFrame 已被排除在外)

final JTextPane textPane = new JTextPane();
textPane.setEditable(false);
final JScrollPane contentPane = new JScrollPane(textPane);
contentPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

这是丑陋的自动添加测试循环

while (true)
try {
Thread.sleep(1000);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
JScrollBar scrollBar = scroll;
boolean preCheck = ((scrollBar.getVisibleAmount() != scrollBar.getMaximum()) && (scrollBar.getValue() + scrollBar.getVisibleAmount() == scrollBar.getMaximum()));
System.out.println("Value: " + scroll.getValue()
+ " | Visible: " + scrollBar.getVisibleAmount()
+ " | Maximum: " + scrollBar.getMaximum()
+ " | Combined: " + (scrollBar.getValue() + scrollBar.getVisibleAmount())
+ " | Vis!=Max : " + (scrollBar.getVisibleAmount() != scrollBar.getMaximum())
+ " | Comb=Max: " + (scrollBar.getValue() + scrollBar.getVisibleAmount() == scrollBar.getMaximum())
+ " | Eval: " + preCheck);
StyledDocument doc = textPane.getStyledDocument();
doc.insertString(doc.getLength(), "FAGAHSIDFNJASDKFJSD\n", doc.getStyle(""));
if (!preCheck)
textPane.setCaretPosition(doc.getLength());
} catch (BadLocationException ex) {
ex.printStackTrace();
}
}
});
} catch (Exception e) {
e.printStackTrace();
}

它不漂亮,但它完成了工作。

这是相关检查

 boolean preCheck = ((scrollBar.getVisibleAmount() != scrollBar.getMaximum()) && (scrollBar.getValue() + scrollBar.getVisibleAmount() == scrollBar.getMaximum()));
if (preCheck)
textPane.setCaretPosition(doc.getLength());

这就是给我带来麻烦的部分。首先检查栏是否可见但不可用(没有足够的文本,使栏成为全长),然后检查栏的底部是否等于最大值。从理论上讲,这应该有效。然而,包括四处移动支票在内的任何事情都没有得到我想要的结果。

有什么建议吗?

不是 this 的重复项或 this ,因为他们希望它始终滚动,而不仅仅是有时。

最佳答案

编辑:

我用更灵活的版本替换了以下代码,该版本适用于 JScrollPane 中的任何组件。查看:Smart Scrolling .

import java.awt.*;
import java.awt.event.*;
import java.util.Date;
import javax.swing.*;
import javax.swing.text.*;

public class ScrollControl implements AdjustmentListener
{
private JScrollBar scrollBar;
private JTextComponent textComponent;
private int previousExtent = -1;

public ScrollControl(JScrollPane scrollPane)
{
Component view = scrollPane.getViewport().getView();

if (! (view instanceof JTextComponent))
throw new IllegalArgumentException("Scrollpane must contain a JTextComponent");

textComponent = (JTextComponent)view;

scrollBar = scrollPane.getVerticalScrollBar();
scrollBar.addAdjustmentListener( this );
}

@Override
public void adjustmentValueChanged(final AdjustmentEvent e)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
checkScrollBar(e);
}
});
}

private void checkScrollBar(AdjustmentEvent e)
{
// The scroll bar model contains information needed to determine the
// caret update policy.

JScrollBar scrollBar = (JScrollBar)e.getSource();
BoundedRangeModel model = scrollBar.getModel();
int value = model.getValue();
int extent = model.getExtent();
int maximum = model.getMaximum();
DefaultCaret caret = (DefaultCaret)textComponent.getCaret();

// When the size of the viewport changes there is no need to change the
// caret update policy.

if (previousExtent != extent)
{
// When the height of a scrollpane is decreased the scrollbar is
// moved up from the bottom for some reason. Reposition the
// scrollbar at the bottom

if (extent < previousExtent
&& caret.getUpdatePolicy() == DefaultCaret.UPDATE_WHEN_ON_EDT)
{
scrollBar.setValue( maximum );
}

previousExtent = extent;
return;
}

// Text components will not scroll to the bottom of a scroll pane when
// a bottom inset is used. Therefore the location of the scrollbar,
// the height of the viewport, and the bottom inset value must be
// considered when determining if the scrollbar is at the bottom.

int bottom = textComponent.getInsets().bottom;

if (value + extent + bottom < maximum)
{
if (caret.getUpdatePolicy() != DefaultCaret.NEVER_UPDATE)
caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
}
else
{
if (caret.getUpdatePolicy() != DefaultCaret.UPDATE_WHEN_ON_EDT)
{
caret.setDot(textComponent.getDocument().getLength());
caret.setUpdatePolicy(DefaultCaret.UPDATE_WHEN_ON_EDT);
}
}
}

private static void createAndShowUI()
{
JPanel center = new JPanel( new GridLayout(1, 2) );
String text = "1\n2\n3\n4\n5\n6\n7\n8\n9\n0\n";

final JTextArea textArea = new JTextArea();
textArea.setText( text );
textArea.setEditable( false );
center.add( createScrollPane( textArea ) );
System.out.println(textArea.getInsets());

final JTextPane textPane = new JTextPane();
textPane.setText( text );
textPane.setEditable( false );
center.add( createScrollPane( textPane ) );
textPane.setMargin( new Insets(5, 3, 7, 3) );
System.out.println(textPane.getInsets());

JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(center, BorderLayout.CENTER);
frame.setSize(500, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);

Timer timer = new Timer(2000, new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
try
{
Date now = new Date();
textArea.getDocument().insertString(textArea.getDocument().getLength(), "\n" + now.toString(), null);
textPane.getDocument().insertString(textPane.getDocument().getLength(), "\n" + now.toString(), null);
}
catch (BadLocationException e1) {}
}
});
timer.start();
}

private static JComponent createScrollPane(JComponent component)
{
JScrollPane scrollPane = new JScrollPane(component);
new ScrollControl( scrollPane );

return scrollPane;
}

public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}

关于java - 智能 JScrollPane 自动滚动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3392290/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com