Adjusting a JScrollPane with nested child JComponents

In Robot Overlord have a JScrollPane in Java Swing and inside it is a JPanel that contains other JPanels and so on and way WAY down at the bottom were the selectable elements like JTextField and JButton. When I hit the TAB key (or SHIFT+TAB) to move focus between components I want the newly focussed component to stay on screen – in other words, make the computer move the scroll bars just enough to bring the focus component into view in the Viewport.

The top answer I could find on Stack Exchange said to do either

// either call on child with zero offset
child.scrollRectToVisible(new Rectangle(child.getSize());
// or call on child's parent with child bounds

Which sounds great, but doesn’t work with nested items. JComponent.getSize() won’t return the absolute position of the component relative to the top-most JPanel in the Viewport. JComponent.getBounds() is slightly better, with an X and Y value relative to its parent.

The solution

Recursion to the rescue!

public void focusGained(FocusEvent e) {
    // the thing that got focus
    Component c = e.getComponent();
    // the bounds of the element
    Rectangle rec = c.getBounds();
    // add up all the parent offsets until we get to the JScrollPane.
    Container c0 = null;
    Container c1 = c.getParent();
    while( (c1!=null) && !(c1 instanceof JScrollPane) ) {
        Rectangle r2 = c1.getBounds();
        rec.x += r2.x;
        rec.y += r2.y;
        // don't forget the last component before the JScrollPane.
        // we'll need it later.
        c0 = c1;
        c1 = c1.getParent();

It would have been really nice if calling scrollRectToVisible() on the first component would work its way up the parent chain automatically, but until that beautiful day this is your workaround.


Throwback to 2010: my first robot, SPIDEE-1

This blast from the past came up in my news feed today. In 2010 I didn’t know anything about building robots, I didn’t have CNC machines or laser cutters or even a 3D printer. I made my first parts from foam core and hot glue! Wild times, wild times.

Point being don’t let your tools stop you, don’t let your talent stop you. All you have to do is have the will to figure out a solution.

If there’s one piece of advice I can add… Someone already went through the pain of figuring out an easier way to do things. I’ve been there so many times: working on some small job N times and it’s always around N*90% that things start to get into a really good rhythm and I wonder “why couldn’t someone show me this technique at the start?”. So my point! My point: you find them and copy their method? That’s called “doing your homework”. You refine it and get really good at it? That’s called “practice”. Do these things. They help you get better faster, the most efficient way to make more stuff.

Unless you know a faster way. Then tell me because I want to copy your method.