4

Background

Looking to add a scroll-lock button to the corner of JScrollPane without obscuring the view port contents. The following image shows a JScrollPane wrapped in a SwingNode within a JavaFX application:

Actual

The lower-right corner shows a button with a lock icon that may be toggled, which is the desired result:

Final

Notice how the content at the very bottom of the view port---the portion beside the lock button---is visible. (Clicking the button will simulate pressing the scroll-lock button on the keyboard. Having a scroll-lock button at the top is perfectly fine, if that's any easier.)

Problem

The JScrollPane API shows the following image:

JScrollPane

Enabling the corner component also seems to require adding a column header. The addition of the header obscures part of the view port, in direct proportion to the scroll-lock button height. Here's a screenshot showing the visible column header, which hides part of the document:

Obscured output

Ideas

I've tried making the header view panel transparent, to no avail.

Code

The relevant code within the SwingNode:

// FlyingSaucer subclass
mView = new HtmlPanel(); 
mScrollPane = new JScrollPane( mView );
setContent( mScrollPane );

final var lock = new JButton( "X" );
mScrollPane.setCorner( UPPER_TRAILING_CORNER, lock );
mScrollPane.setVerticalScrollBarPolicy( VERTICAL_SCROLLBAR_ALWAYS );

final var header = new JPanel();
header.setPreferredSize(
  new Dimension( 12, lock.getPreferredSize().height ) );
header.setOpaque( false );
header.setBackground( new Color( 0, 0, 0, 0 ) );
mScrollPane.setColumnHeaderView( header );

See camickr's answer for another example.

Question

How would you add a button to JScrollPane's bottom (or top) corner such that no view port content is obscured?

Related

Dave Jarvis
  • 28,853
  • 37
  • 164
  • 291
  • So if the corner components are ruled out, would it make sense to provide a custom scrollbar component that allows rendering the scroll lock? I guess the scroll lock functionality is connected to scrolling anyway, so you could create a 'LockableScrollbar'. – Hiran Chaudhuri Feb 23 '21 at 07:12
  • If you are willing to always display the horizontal scrollbar as well, then you will always have a space in the bottom, right corner for a corner component. – Abra Feb 23 '21 at 08:12

1 Answers1

1

I would suggest using "wrapper" panels to achieve you desired layout. Something like:

JButton scrollLock = new JButton("...");

JScrollPane scrollPane = new JScrollPane(...);
JScrollBar verticalBar = scrollPane.getVerticalScrollBar();

JPanel verticalPanel = new JPanel( new BorderLayout() );
verticalPanel.add(verticalBar, BorderLayout.CENTER);
verticalPanel.add(scrollLock, BorderLayout.PAGE_END);

JPanel wrapper = new JPanel( new BorderLayout() );
wrapper.add(scrollPane, BorderLayout.CENTER);
wrapper.add(verticalPanel, BorderLayout.LINE_END);

setContent(wrapper);
camickr
  • 308,339
  • 18
  • 152
  • 272
  • It's a [bit beefy](https://i.ibb.co/Fq0NDCY/scrollbar-04.png) without setting the preferred dimensions, but definitely workable. – Dave Jarvis Feb 23 '21 at 16:52
  • 1
    If you are adding a JButton you can use the `setMargin(...)` method to remove extra space around your text/icon. The width of the button will control the width of the scroll bar. – camickr Feb 23 '21 at 19:12