I have need to scroll a webview when the user has focus in a different window.
The only way i found to achieve what i needed was via an "unsafe" reflections call. I tried first getting the scrollbar and setting value to it, its value changed but it had no effect on what was shown in the webview.
After a lot of trial and error i finally came up with this solution:
Platform.runLater(new Runnable() {
@Override
public void run() {
try {
final Method declaredMethod = webView.getClass().getDeclaredMethod("processKeyEvent", KeyEvent.class);
final KeyEvent keyEvent = new KeyEvent(null, null, KeyEvent.KEY_PRESSED, null, null, KeyCode.PAGE_DOWN, false, false, false, false);
declaredMethod.setAccessible(true);
declaredMethod.invoke(webView, keyEvent);
} catch (NoSuchMethodException ex) {
Logger.getLogger(JavaFXBrowserImplementation.class.getName()).log(Level.SEVERE, null, ex);
} catch (SecurityException ex) {
Logger.getLogger(JavaFXBrowserImplementation.class.getName()).log(Level.INFO, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(JavaFXBrowserImplementation.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalArgumentException ex) {
Logger.getLogger(JavaFXBrowserImplementation.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvocationTargetException ex) {
Logger.getLogger(JavaFXBrowserImplementation.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
It should be possible to in some way scroll to a specific x,y coordinate without the use of javascripts or reflection
attempt that change the value of the scrollbar but not what is actually shown in the webview
public ScrollBar getVerticalScrollBar() {
final Set<Node> nodes = webView.lookupAll(".scroll-bar");
for (Node node : nodes) {
if (ScrollBar.class.isInstance(node)) {
final ScrollBar scroll = (ScrollBar) node;
if (scroll.getOrientation() == Orientation.VERTICAL) {
return scroll;
}
}
}
return null;
}
public void scrollPageDown() {
final ScrollBar scroll = getVerticalScrollBar();
final double min = scroll.getMin();
final double max = scroll.getMax();
final double value = scroll.getValue();
final double pageHeight = webView.getBoundsInParent().getHeight() - 10;
final double scrollX = Math.min(max, value + pageHeight);
System.out.println("scrollPageDown()");
System.out.println(" min: " + min);
System.out.println(" max: " + max);
System.out.println(" value: " + value);
System.out.println(" pageHeight: " + pageHeight);
System.out.println(" Math.min(max, value + pageHeight) = " + scrollX);
Platform.runLater(new Runnable() {
@Override
public void run() {
scroll.setValue(Math.min(max, value + pageHeight));
}
});
The only way i found to achieve what i needed was via an "unsafe" reflections call. I tried first getting the scrollbar and setting value to it, its value changed but it had no effect on what was shown in the webview.
After a lot of trial and error i finally came up with this solution:
Platform.runLater(new Runnable() {
@Override
public void run() {
try {
final Method declaredMethod = webView.getClass().getDeclaredMethod("processKeyEvent", KeyEvent.class);
final KeyEvent keyEvent = new KeyEvent(null, null, KeyEvent.KEY_PRESSED, null, null, KeyCode.PAGE_DOWN, false, false, false, false);
declaredMethod.setAccessible(true);
declaredMethod.invoke(webView, keyEvent);
} catch (NoSuchMethodException ex) {
Logger.getLogger(JavaFXBrowserImplementation.class.getName()).log(Level.SEVERE, null, ex);
} catch (SecurityException ex) {
Logger.getLogger(JavaFXBrowserImplementation.class.getName()).log(Level.INFO, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(JavaFXBrowserImplementation.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalArgumentException ex) {
Logger.getLogger(JavaFXBrowserImplementation.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvocationTargetException ex) {
Logger.getLogger(JavaFXBrowserImplementation.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
It should be possible to in some way scroll to a specific x,y coordinate without the use of javascripts or reflection
attempt that change the value of the scrollbar but not what is actually shown in the webview
public ScrollBar getVerticalScrollBar() {
final Set<Node> nodes = webView.lookupAll(".scroll-bar");
for (Node node : nodes) {
if (ScrollBar.class.isInstance(node)) {
final ScrollBar scroll = (ScrollBar) node;
if (scroll.getOrientation() == Orientation.VERTICAL) {
return scroll;
}
}
}
return null;
}
public void scrollPageDown() {
final ScrollBar scroll = getVerticalScrollBar();
final double min = scroll.getMin();
final double max = scroll.getMax();
final double value = scroll.getValue();
final double pageHeight = webView.getBoundsInParent().getHeight() - 10;
final double scrollX = Math.min(max, value + pageHeight);
System.out.println("scrollPageDown()");
System.out.println(" min: " + min);
System.out.println(" max: " + max);
System.out.println(" value: " + value);
System.out.println(" pageHeight: " + pageHeight);
System.out.println(" Math.min(max, value + pageHeight) = " + scrollX);
Platform.runLater(new Runnable() {
@Override
public void run() {
scroll.setValue(Math.min(max, value + pageHeight));
}
});