Reputation: 719
I have a JTextArea with a long text. In the text there is the string "abc" that I want to be displayed in the middle (vertical) of the text area. I can use setCaretPosition to cause the ScrollPane to scroll enough for the string "abc" to scroll into view. The scrolling continues until the text "abc" becomes visible at the bottom of the text area (see example) How can I get the scrollbar to scroll so far that the text "abc" is displayed in the middle (vertically) in the visible area?
many thanks for your help!
public class TestCenter {
public TestCenter() {
JFrame frame = new JFrame();
JTextArea ta = new JTextArea();
frame.setMinimumSize(new Dimension(800, 600));
frame.add(new JScrollPane(ta));
frame.pack();
frame.setVisible(true);
SwingUtilities.invokeLater(() -> {
StringBuilder testText = new StringBuilder();
for (int t = 0; t < 100; t++) {
testText.append("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n");
}
testText.append("abc");
for (int t = 0; t < 100; t++) {
testText.append("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n");
}
ta.setText(testText.toString());
ta.setCaretPosition(testText.indexOf("abc"));
});
}
public static void main(String[] args) {
new TestCenter();
}
}
Upvotes: 1
Views: 105
Reputation: 5931
To move the scroll bar to the position of the abc
text to be displayed vertically in the middle of the viewport we have to first find the line number of the text and translate it to the view coordinates:
// Find the line number of the "abc" text
int lineNumber = ta.getLineOfOffset(testText.indexOf("abc"));
// Translate the lineNumber to the view rectangle
Rectangle viewRect = ta.modelToView(ta.getLineStartOffset(lineNumber));
Now, having the viewRect
we can get the viewport size and calculate the position Point
to scroll to
Dimension viewportSize = scrollPane.getViewport().getExtentSize();
// Calculate new view position to scroll to
Point scrollPoint = new Point(0, view.y - (viewportSize.height - view.height) / 2);
Some explanation about calculating the scrollPoint
. To calculate the y-coordinate at which the line should be centered, we use the following formula: rect.y - (viewportSize.height - viewRect.height) / 2
.
We subtract the height of the line (viewRect.height
) from the total viewport size (viewportSize.height
) which gives the remaining space in the viewport above and below the line. Then we divide the remaining space by 2
to get the position of the line in the center of viewport.
And as we want to vertically center the line in the viewport, we subtract the resulting value from the top y-coordinate of the line to get the new y-coordinate of the viewport.
Finally, we can set the viewport to the calculated scrollPoint
using JViewport::setViewPosition(Point)
:
public TestCenter() {
JFrame frame = new JFrame();
JTextArea ta = new JTextArea();
JScrollPane scrollPane = new JScrollPane(ta);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setMinimumSize(new Dimension(800, 600));
frame.add(scrollPane);
frame.pack();
frame.setVisible(true);
var testText =
"xxxxxxxxxxxxxxxxxxxx\n".repeat(100) +
"abc" +
"xxxxxxxxxxxxxxxxxxxx\n".repeat(100);
ta.setText(testText.toString());
try {
// Find the line number of the "abc" text
int lineNumber = ta.getLineOfOffset(testText.indexOf("abc"));
// Translate the lineNumber to the view rectangle
Rectangle viewRect = ta.modelToView(ta.getLineStartOffset(lineNumber));
// Get the size of the viewport
Dimension viewportSize = scrollPane.getViewport().getExtentSize();
// Calculate new view position to scroll to
Point scrollPoint = new Point(0, viewRect.y - (viewportSize.height - viewRect.height) / 2);
// Move the view to the new position
scrollPane.getViewport().setViewPosition(scrollPoint);
} catch (BadLocationException e) {
throw new RuntimeException(e);
}
}
Upvotes: 2