如何 set/remember JavaFX 8 WebView 中的滚动条缩略图位置?
How to set/remember scrollbar thumb position in JavaFX 8 WebView?
我对 JavaFX 8 WebView 及其滚动条有疑问。
我想重新加载 HTML 文档并记住当前的垂直滚动条位置。不幸的是,每当我重新加载文档时,滚动条都会移动到其初始位置。如何强制滚动条记住它的位置?
我解决这个问题的尝试:
通过 WebView#lookup(String id)
(参见 1)可以访问 WebView 实例的垂直和水平 ScrollBar
实例。这使我能够掌握当前的滚动条值,即通过 ScrollBar#getValue()
的拇指位置。不幸的是,通过 ScrollBar#setValue(double value)
设置值并没有达到预期的效果。滚动条滑块位置保持不变。
此外,我怀疑未呈现 JavaFX 滚动条。相反,似乎显示了具有类似样式的 WebKit 滚动条。至少通过 Scenic View 的简短场景图分析给我这样的印象。
这是 JavaFX 错误吗?有没有办法实现所需的行为?
这里有一个演示 setValue() 问题的示例程序:
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;
}
}
相关问题:How to hide scrollbars in the JavaFX WebView
我找到了解决方案:
可以通过使用 JavaScript 实现所需的行为。大多数代码示例通过 WebView#getEngine()#loadContent(String content)
将 JavaScript 代码直接注入到内容中。但是,对于 URL,这不起作用。但是网络引擎提供了直接JavaScript执行的方法:
webView.getEngine().executeScript("// javascript code");
以下是我用来控制滚动条的方法:
/**
* Scrolls to the specified position.
* @param view web view that shall be scrolled
* @param x horizontal scroll value
* @param y vertical scroll value
*/
public void scrollTo(WebView view, int x, int y) {
view.getEngine().executeScript("window.scrollTo(" + x + ", " + y + ")");
}
/**
* Returns the vertical scroll value, i.e. thumb position.
* This is equivalent to {@link javafx.scene.control.ScrollBar#getValue().
* @param view
* @return vertical scroll value
*/
public int getVScrollValue(WebView view) {
return (Integer) view.getEngine().executeScript("document.body.scrollTop");
}
/**
* Returns the horizontal scroll value, i.e. thumb position.
* This is equivalent to {@link javafx.scene.control.ScrollBar#getValue()}.
* @param view
* @return horizontal scroll value
*/
public int getHScrollValue(WebView view) {
return (Integer) view.getEngine().executeScript("document.body.scrollLeft");
}
/**
* Returns the maximum vertical scroll value.
* This is equivalent to {@link javafx.scene.control.ScrollBar#getMax()}.
* @param view
* @return vertical scroll max
*/
public int getVScrollMax(WebView view) {
return (Integer) view.getEngine().executeScript("document.body.scrollWidth");
}
/**
* Returns the maximum horizontal scroll value.
* This is equivalent to {@link javafx.scene.control.ScrollBar#getMax()}.
* @param view
* @return horizontal scroll max
*/
public int getHScrollMax(WebView view) {
return (Integer) view.getEngine().executeScript("document.body.scrollHeight");
}
这是问题代码的工作版本:
import java.util.Set;
import javafx.application.Application;
import javafx.collections.ListChangeListener;
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");
// change scrollbar value, i.e., thumb position via button
Button btn = new Button();
btn.setText("Move ScrollBar");
btn.setOnAction((ActionEvent event) -> {
int value = 2000;
System.out.println(">> current value: " + getVScrollValue(view));
System.out.println(">> setting scrollbar value to " + value);
scrollTo(view, 0, 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);
}
/**
* Scrolls to the specified position.
* @param view web view that shall be scrolled
* @param x horizontal scroll value
* @param y vertical scroll value
*/
public void scrollTo(WebView view, int x, int y) {
view.getEngine().executeScript("window.scrollTo(" + x + ", " + y + ")");
}
/**
* Returns the vertical scroll value, i.e. thumb position.
* This is equivalent to {@link javafx.scene.control.ScrollBar#getValue().
* @param view
* @return vertical scroll value
*/
public int getVScrollValue(WebView view) {
return (Integer) view.getEngine().executeScript("document.body.scrollTop");
}
/**
* Returns the horizontal scroll value, i.e. thumb position.
* This is equivalent to {@link javafx.scene.control.ScrollBar#getValue()}.
* @param view
* @return horizontal scroll value
*/
public int getHScrollValue(WebView view) {
return (Integer) view.getEngine().executeScript("document.body.scrollLeft");
}
/**
* Returns the maximum vertical scroll value.
* This is equivalent to {@link javafx.scene.control.ScrollBar#getMax()}.
* @param view
* @return vertical scroll max
*/
public int getVScrollMax(WebView view) {
return (Integer) view.getEngine().executeScript("document.body.scrollWidth");
}
/**
* Returns the maximum horizontal scroll value.
* This is equivalent to {@link javafx.scene.control.ScrollBar#getMax()}.
* @param view
* @return horizontal scroll max
*/
public int getHScrollMax(WebView view) {
return (Integer) view.getEngine().executeScript("document.body.scrollHeight");
}
}
我对 JavaFX 8 WebView 及其滚动条有疑问。
我想重新加载 HTML 文档并记住当前的垂直滚动条位置。不幸的是,每当我重新加载文档时,滚动条都会移动到其初始位置。如何强制滚动条记住它的位置?
我解决这个问题的尝试:
通过 WebView#lookup(String id)
(参见 1)可以访问 WebView 实例的垂直和水平 ScrollBar
实例。这使我能够掌握当前的滚动条值,即通过 ScrollBar#getValue()
的拇指位置。不幸的是,通过 ScrollBar#setValue(double value)
设置值并没有达到预期的效果。滚动条滑块位置保持不变。
此外,我怀疑未呈现 JavaFX 滚动条。相反,似乎显示了具有类似样式的 WebKit 滚动条。至少通过 Scenic View 的简短场景图分析给我这样的印象。
这是 JavaFX 错误吗?有没有办法实现所需的行为?
这里有一个演示 setValue() 问题的示例程序:
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;
}
}
相关问题:How to hide scrollbars in the JavaFX WebView
我找到了解决方案:
可以通过使用 JavaScript 实现所需的行为。大多数代码示例通过 WebView#getEngine()#loadContent(String content)
将 JavaScript 代码直接注入到内容中。但是,对于 URL,这不起作用。但是网络引擎提供了直接JavaScript执行的方法:
webView.getEngine().executeScript("// javascript code");
以下是我用来控制滚动条的方法:
/**
* Scrolls to the specified position.
* @param view web view that shall be scrolled
* @param x horizontal scroll value
* @param y vertical scroll value
*/
public void scrollTo(WebView view, int x, int y) {
view.getEngine().executeScript("window.scrollTo(" + x + ", " + y + ")");
}
/**
* Returns the vertical scroll value, i.e. thumb position.
* This is equivalent to {@link javafx.scene.control.ScrollBar#getValue().
* @param view
* @return vertical scroll value
*/
public int getVScrollValue(WebView view) {
return (Integer) view.getEngine().executeScript("document.body.scrollTop");
}
/**
* Returns the horizontal scroll value, i.e. thumb position.
* This is equivalent to {@link javafx.scene.control.ScrollBar#getValue()}.
* @param view
* @return horizontal scroll value
*/
public int getHScrollValue(WebView view) {
return (Integer) view.getEngine().executeScript("document.body.scrollLeft");
}
/**
* Returns the maximum vertical scroll value.
* This is equivalent to {@link javafx.scene.control.ScrollBar#getMax()}.
* @param view
* @return vertical scroll max
*/
public int getVScrollMax(WebView view) {
return (Integer) view.getEngine().executeScript("document.body.scrollWidth");
}
/**
* Returns the maximum horizontal scroll value.
* This is equivalent to {@link javafx.scene.control.ScrollBar#getMax()}.
* @param view
* @return horizontal scroll max
*/
public int getHScrollMax(WebView view) {
return (Integer) view.getEngine().executeScript("document.body.scrollHeight");
}
这是问题代码的工作版本:
import java.util.Set;
import javafx.application.Application;
import javafx.collections.ListChangeListener;
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");
// change scrollbar value, i.e., thumb position via button
Button btn = new Button();
btn.setText("Move ScrollBar");
btn.setOnAction((ActionEvent event) -> {
int value = 2000;
System.out.println(">> current value: " + getVScrollValue(view));
System.out.println(">> setting scrollbar value to " + value);
scrollTo(view, 0, 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);
}
/**
* Scrolls to the specified position.
* @param view web view that shall be scrolled
* @param x horizontal scroll value
* @param y vertical scroll value
*/
public void scrollTo(WebView view, int x, int y) {
view.getEngine().executeScript("window.scrollTo(" + x + ", " + y + ")");
}
/**
* Returns the vertical scroll value, i.e. thumb position.
* This is equivalent to {@link javafx.scene.control.ScrollBar#getValue().
* @param view
* @return vertical scroll value
*/
public int getVScrollValue(WebView view) {
return (Integer) view.getEngine().executeScript("document.body.scrollTop");
}
/**
* Returns the horizontal scroll value, i.e. thumb position.
* This is equivalent to {@link javafx.scene.control.ScrollBar#getValue()}.
* @param view
* @return horizontal scroll value
*/
public int getHScrollValue(WebView view) {
return (Integer) view.getEngine().executeScript("document.body.scrollLeft");
}
/**
* Returns the maximum vertical scroll value.
* This is equivalent to {@link javafx.scene.control.ScrollBar#getMax()}.
* @param view
* @return vertical scroll max
*/
public int getVScrollMax(WebView view) {
return (Integer) view.getEngine().executeScript("document.body.scrollWidth");
}
/**
* Returns the maximum horizontal scroll value.
* This is equivalent to {@link javafx.scene.control.ScrollBar#getMax()}.
* @param view
* @return horizontal scroll max
*/
public int getHScrollMax(WebView view) {
return (Integer) view.getEngine().executeScript("document.body.scrollHeight");
}
}