私は、Adium や私が見た他のほとんどのチャット クライアントの機能を模倣しようとしています。この機能では、新しいメッセージが着信するとスクロールバーが一番下に進みますが、それは既にそこにいる場合のみです。言い換えれば、数行上にスクロールして読んでいる場合、新しいメッセージが入ってきても、あなたの位置が画面の一番下にジャンプすることはありません。それは迷惑だろう。しかし、一番下までスクロールすると、常に最新のメッセージを表示したいとプログラムが想定し、それに応じて自動スクロールします。
私はこれを真似しようとしてしばらく苦労しました。プラットフォームは、あらゆる犠牲を払ってこの動作と戦っているようです。私ができる最善のことは次のとおりです。
コンストラクターで:
JTextArea chatArea = new JTextArea();
JScrollPane chatAreaScrollPane = new JScrollPane(chatArea);
// We will manually handle advancing chat window
DefaultCaret caret = (DefaultCaret) chatArea.getCaret();
caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
入ってくる新しいテキストを処理するメソッド:
boolean atBottom = isViewAtBottom();
// Append the text using styles etc to the chatArea
if (atBottom) {
scrollViewportToBottom();
}
public boolean isAtBottom() {
// Is the last line of text the last line of text visible?
Adjustable sb = chatAreaScrollPane.getVerticalScrollBar();
int val = sb.getValue();
int lowest = val + sb.getVisibleAmount();
int maxVal = sb.getMaximum();
boolean atBottom = maxVal == lowest;
return atBottom;
}
private void scrollToBottom() {
chatArea.setCaretPosition(chatArea.getDocument().getLength());
}
さて、これは機能しますが、2 つの理由からぎこちなく、理想的ではありません。
- キャレットの位置を設定すると、ユーザーがチャット領域で行った選択がすべて消去されます。彼がコピー/貼り付けをしようとしている場合、これは非常にイライラするだろうと想像できます.
- スクロール ペインの進行はテキストが挿入された後に発生するため、スクロールバーが間違った位置にある一瞬があり、その後視覚的に最後に向かってジャンプします。これは理想的ではありません。
あなたが尋ねる前に、はい、私はこのブログ投稿を読みましたText Area Scrollingですが、デフォルトのスクロールから下への動作は私が望むものではありません。
その他の関連する (ただし、私の考えでは、この点で完全に役立つわけではありません) 質問: jscrollpane にスクロール バーを設定 する
この点で何か助けていただければ幸いです。
編集:
Devon_C_Miller のアドバイスに従って、一番下までスクロールする方法が改善され、問題 #1 が解決されました。
private void scrollToBottom() {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
int endPosition = chatArea.getDocument().getLength();
Rectangle bottom = chatArea.modelToView(endPosition);
chatArea.scrollRectToVisible(bottom);
}
catch (BadLocationException e) {
System.err.println("Could not scroll to " + e);
}
}
});
}
私はまだ問題#2を持っています。