I have a question regarding the JavaFX 8 WebView and its scrollbars.
I want to reload an HTML document and remember the current vertical scrollbar position. Unfortunately, the scrollbar moves to its initial position whenever I reload the document. How can I force the scrollbar to remember its position?
My attempts to solve this problem:
Via WebView#lookup(String id)
(see 1) it is possible to access the vertical and horizontal ScrollBar
instances of a WebView instance. This allows me to get hold of the current scrollbar value, i.e. thumb position via ScrollBar#getValue()
. Unfortunately, setting the value via ScrollBar#setValue(double value)
does not have the desired effect. The scrollbar thumb position remains unchanged.
Furthermore, I suspect that the JavaFX scrollbars are not rendered. Instead it seems that a WebKit scrollbar with similar style is shown instead. At least a brief scene graph analysis via Scenic View gives me this impression.
Is this a JavaFX bug? Is there a way to achieve the desired behavior?
Here is a sample program that demonstrates the setValue()-problem:
import java.util.Set;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollBar;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
/**
* ScrollBar bug in JavaFX 8 WebView?
*
* @author Michael Hoffer <info@michaelhoffer.de>
*/
public class WebViewAndItsScrollBars extends Application {
@Override
public void start(Stage primaryStage) {
// create webview and load content
WebView view = new WebView();
view.getEngine().load(
"https://docs.oracle.com/javase/8/javafx/"
+ "api/javafx/scene/control/ScrollBar.html");
// vertical scrollbar of the webview
ScrollBar vScrollBar = getVScrollBar(view);
// change scrollbar value, i.e., thumb position via button
Button btn = new Button();
btn.setText("Move ScrollBar");
btn.setOnAction((ActionEvent event) -> {
if (vScrollBar != null) {
double value = 2000;
System.out.println(">> current value: " + vScrollBar.getValue());
System.out.println(">> setting scrollbar value to " + value);
vScrollBar.setValue(value);
}
});
// create root layout
VBox root = new VBox();
root.setAlignment(Pos.CENTER);
root.getChildren().add(view);
root.getChildren().add(btn);
// setup and show stage
Scene scene = new Scene(root, 1024, 600);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
/**
* Returns the vertical scrollbar of the webview.
*
* @param webView webview
* @return vertical scrollbar of the webview or {@code null} if no vertical
* scrollbar exists
*/
private ScrollBar getVScrollBar(WebView webView) {
Set<Node> scrolls = webView.lookupAll(".scroll-bar");
for (Node scrollNode : scrolls) {
if (ScrollBar.class.isInstance(scrollNode)) {
ScrollBar scroll = (ScrollBar) scrollNode;
if (scroll.getOrientation() == Orientation.VERTICAL) {
return scroll;
}
}
}
return null;
}
}
Related question: How to hide scrollbars in the JavaFX WebView