JavaFX: Synchronize Editor scrollbar with WebView scrollbar

Thangalin thangalin at gmail.com
Sun Jun 14 23:03:49 UTC 2020


Hey list!

Am wondering how to go about synchronizing scroll bars between a
JavaFX StyleClassedTextArea that uses a VirtualizedScrollPane and a
JavaFX WebView instance. A couple of tangentially-related issues have
appeared:

1. Scrollbar. The documentation states, "WebView handles mouse and
some keyboard events, and manages scrolling automatically, so there's
no need to put it into a ScrollPane." The API appears to prevent
direct access to the scrollbar, forcing JavaScript contortions while
preventing unidirectional binding of scrollbars (that can interject a
ratio calculation).

2. Fading. The default behaviour appears to make the scrollbar
disappear after a few seconds. Since, in this case, the scrollbars are
meant to be synchronized, it would be convenient to disable that
behaviour (i.e., always show the vertical scrollbar).

Both these issues would be reasonably easy to solve if the scrollbar
property for the WebView could be obtained. Here's a snippet showing
the editor beside the preview:

public class ScrollSync extends Application {
  private final StyleClassedTextArea mEditor =
      new StyleClassedTextArea( false );
  private final VirtualizedScrollPane<StyleClassedTextArea> mEditorScrollPane =
      new VirtualizedScrollPane<>( mEditor );

  private final WebView mWebView = new WebView();
  private final String mHtml =
      "<!DOCTYPE html><html><body>%CONTENT%</body></html>";

  public static void main( final String[] args ) {
    launch( args );
  }

  @Override
  public void start( final Stage stage ) {
    mEditorScrollPane.setVbarPolicy( ScrollPane.ScrollBarPolicy.ALWAYS );

    mEditor.textProperty().addListener(
        ( observable, oldValue, newValue ) -> {
          mWebView.getEngine().loadContent(
              mHtml.replace( "%CONTENT%", newValue )
          );
        }
    );

    final SplitPane splitPane = new SplitPane(
        mEditorScrollPane,
        mWebView
    );

    stage.setScene( new Scene( splitPane, 800, 400 ) );
    stage.show();
  }
}

In the screenshot, notice that the WebView can contain images, which
affects the relative heights of the scrollbars; also notice that the
scrollbar has faded out from the WebView:

https://i.stack.imgur.com/QJFnY.png

Although the cursor and scrollbar are positioned at the bottom of the
text editor, the WebView remains scrolled to the top, rather than the
bottom.

I am wondering:

(a) Without resorting to using JavaScript's scrollTo functions, how
would you ensure that the scrollbar from WebView reflects the relative
vertical scrolling offset of the editor pane?

(b) How would you make sure the WebView scrollbar is always visible?
(I tried many CSS variations, but none would eliminate the fade out
animation.)

The editor's architecture being implemented resembles the "Example
Processing Combination" panel in the following figure:

https://i.stack.imgur.com/s1QwK.png

There's no simple way for the editor to communicate with the resulting
HTML displayed by WebView, which makes passing values that reflect the
editor's scrollbar into a JavaScript function non-trivial (because the
text could be processed in many ways prior to reaching the WebView). A
unidirectional binding at the "pane" would avoid the architectural
separation issue altogether, alleviating the need for an inter-pane
communication protocol.

Thank you!
TX


More information about the openjfx-dev mailing list