在 JavaFX 中从另一个 WebView 更改一个 WebView
Changing one WebView from another WebView in JavaFX
我目前有两个 WebView(比如 leftWebView 和 rightWebView),它们位于嵌入 Anchor Pane 内的水平 SplitPane 中。每个 WebView 都有一个 JavaScript(创建一个具有不同颜色的矩形)。现在我想做的是在单击一个矩形时,我想更改另一个 WebView。问这个问题的一个简单方法是如何通过更改 rightWebView 来调用 leftWebView。
我的应用程序的 UI 看起来像这样:Sample Application
以下是 FXML、控制器和 Java 文件
public class Demo2 extends Application {
@Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
public class FXMLDocumentController implements Initializable {
@FXML
private LeftWebView wvLeftWebView ;
@FXML
private RightWebView wvRightWebView ;
@FXML
public void myCustomAction(ActionEvent event) {
System.out.println("mCustomAction(): Caught an event ");
}
@Override
public void initialize(URL url, ResourceBundle rb) {
}
}
LeftWebView 和 RightWebView class 相似,只是 javascript
public class LeftWebView extends Region{
WebView webView = new WebView();
WebEngine webEngine = webView.getEngine();
public LeftWebView(){
// final URL urlHello = getClass().getResource("TimeGraph.html");
// webEngine.load(urlHello.toExternalForm());
webEngine.getLoadWorker().stateProperty().addListener(
new ChangeListener<Worker.State>() {
public void changed(ObservableValue<? extends Worker.State> p, Worker.State oldState, Worker.State newState) {
if (newState == Worker.State.SUCCEEDED) {
JSObject win = (JSObject) webEngine.executeScript("window");
win.setMember("javaObj", new Bridge());
System.out.println("LeftWebView(): Constructor");
}
}
}
);
webEngine.loadContent(
"<div style='width: 100; height: 100; background: green;' " +
"onclick='javaObj.clickLeft();' />"
);
getChildren().add(webView);
}
@Override
protected void layoutChildren(){
double w = getWidth();
double h = getHeight();
layoutInArea(webView, 0, 0, w, h, 0, HPos.CENTER, VPos.CENTER);
// layoutInArea(toolbar, 0, h-toolbarHeight, w, toolbarHeight, 0, HPos.CENTER, VPos.CENTER);
}
}
public class Bridge {
public void clickRight() {
System.out.println("Bridge.clickRight() called");
}
public void clickLeft() throws IOException {
System.out.println("Bridge.clickLeft() called");
WebView webView = new WebView();
WebEngine webEngine = webView.getEngine();
webEngine.getLoadWorker().stateProperty().addListener(
new ChangeListener<Worker.State>() {
public void changed(ObservableValue<? extends Worker.State> p, Worker.State oldState, Worker.State newState) {
if (newState == Worker.State.SUCCEEDED) {
JSObject win = (JSObject) webEngine.executeScript("window");
win.setMember("javaObj", new Bridge());
System.out.println("Bridge.clickLeft(): property Changed of LeftWebView");
}
}
}
);
webEngine.loadContent(
"<div style='width: 200; height: 200; background: blue;' " +
"onclick='javaObj.test2();' />"
);
/*
FXMLLoader fxmlLoader = new FXMLLoader();
Pane p = fxmlLoader.load(getClass().getResource("FXMLDocument.fxml").openStream());
FXMLDocumentController fooController = (FXMLDocumentController) fxmlLoader.getController();
*/
/*
URL location = getClass().getResource("MyController.fxml");
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(location);
Parent root = (Parent) fxmlLoader.load(location.openStream());
// How to get the handler for a specific element of my FXML
*/
}
}
<?import javafx.scene.web.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import demo2.RightWebView?>
<?import demo2.LeftWebView?>
<?import demo2.FXMLDocumentController?>
<AnchorPane fx:controller="demo2.FXMLDocumentController" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8">
<SplitPane dividerPositions="0.4765886287625418" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity"
prefHeight="400.0" prefWidth="600.0" >
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<LeftWebView id="webLeft" fx:id="wvLeftWebView" prefHeight="-1.0" prefWidth="-1.0" onAction="#myCustomAction" />
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<RightWebView id="webRight" fx:id="wvRightWebView" prefHeight="-1.0" prefWidth="-1.0" />
</children>
</AnchorPane>
</items>
</SplitPane>
</AnchorPane>
我可以通过 Java 脚本回调 class Bridge (Bridge.clickLeft()) 中的一个方法,但我不确定如何着手访问另一个方法WebView 并更新它。
我通过其他问题找到了一个简单的解决方案 and
FXML 文件包含两个网页视图和一个标签(标签只是为了显示一个 JavaFX 控件)
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="webviewlabel.FXMLDocumentController">
<children>
<WebView fx:id="wvSample" layoutX="184.0" layoutY="16.0" prefHeight="200.0" prefWidth="175.0" />
<WebView fx:id="wvAffected" layoutY="39.0" prefHeight="177.0" prefWidth="154.0" />
<Label fx:id="lblSample" text="Label" />
</children>
</AnchorPane>
控制器class包含
public class FXMLDocumentController implements Initializable {
@FXML
private Label lblSample;
@FXML
private WebView wvSample;
private WebEngine webSample ;
@FXML
private WebView wvAffected;
private WebEngine webAffected ;
@FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
}
@Override
public void initialize(URL url, ResourceBundle rb) {
// wvSample = new WebView();
initiateWebSample();
initiateWebAffected();
}
public void initiateWebSample() {
webSample = wvSample.getEngine();
webSample.getLoadWorker().stateProperty().addListener(
new ChangeListener<Worker.State>() {
public void changed(ObservableValue<? extends Worker.State> p, Worker.State oldState, Worker.State newState) {
if (newState == Worker.State.SUCCEEDED) {
JSObject win = (JSObject) webSample.executeScript("window");
win.setMember("javaObj", new Connector(FXMLDocumentController.this));
System.out.println("FXMLDocumentController.initiateWebSample(): Called");
}
}
}
);
webSample.loadContent(
"<div style='width: 50; height: 50; background: yellow;' onclick='javaObj.Connecting();' />"
);
}
public void initiateWebAffected() {
webAffected = wvAffected.getEngine();
webAffected.getLoadWorker().stateProperty().addListener(
new ChangeListener<Worker.State>() {
public void changed(ObservableValue<? extends Worker.State> p, Worker.State oldState, Worker.State newState) {
if (newState == Worker.State.SUCCEEDED) {
JSObject win = (JSObject) webAffected.executeScript("window");
win.setMember("javaObj", new Connector(FXMLDocumentController.this));
System.out.println("FXMLDocumentController.initiateWebAffected(): Called");
}
}
}
);
String strJScript = "<div style='width: 50; height: 50; background: blue;' onclick='javaObj.Connecting();' />" ;
webAffected.loadContent(strJScript);
}
public void setLabelText(String text)
{
System.out.println("FXMLDocumentController.setLabelText(): Called");
lblSample.setText(text);
}
public void changeWebViewAffected(String pstrColor) {
String strJScript = "<div style='width: 50; height: 50; background: "+pstrColor+";' onclick='javaObj.Connecting();' />" ;
webAffected.loadContent(strJScript);
}
}
并且连接class包含要调用的方法
public class Connector {
private final FXMLDocumentController controller ;
public Connector(FXMLDocumentController controller) {
this.controller = controller ;
}
public void Connecting() {
try {
System.out.println("Connector.Connecting(): Called");
controller.setLabelText("Bye World");
controller.changeWebViewAffected("green");
} catch (Exception ex) {
Logger.getLogger(Connector.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
我目前有两个 WebView(比如 leftWebView 和 rightWebView),它们位于嵌入 Anchor Pane 内的水平 SplitPane 中。每个 WebView 都有一个 JavaScript(创建一个具有不同颜色的矩形)。现在我想做的是在单击一个矩形时,我想更改另一个 WebView。问这个问题的一个简单方法是如何通过更改 rightWebView 来调用 leftWebView。
我的应用程序的 UI 看起来像这样:Sample Application
以下是 FXML、控制器和 Java 文件
public class Demo2 extends Application {
@Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
public class FXMLDocumentController implements Initializable {
@FXML
private LeftWebView wvLeftWebView ;
@FXML
private RightWebView wvRightWebView ;
@FXML
public void myCustomAction(ActionEvent event) {
System.out.println("mCustomAction(): Caught an event ");
}
@Override
public void initialize(URL url, ResourceBundle rb) {
}
}
LeftWebView 和 RightWebView class 相似,只是 javascript
public class LeftWebView extends Region{
WebView webView = new WebView();
WebEngine webEngine = webView.getEngine();
public LeftWebView(){
// final URL urlHello = getClass().getResource("TimeGraph.html");
// webEngine.load(urlHello.toExternalForm());
webEngine.getLoadWorker().stateProperty().addListener(
new ChangeListener<Worker.State>() {
public void changed(ObservableValue<? extends Worker.State> p, Worker.State oldState, Worker.State newState) {
if (newState == Worker.State.SUCCEEDED) {
JSObject win = (JSObject) webEngine.executeScript("window");
win.setMember("javaObj", new Bridge());
System.out.println("LeftWebView(): Constructor");
}
}
}
);
webEngine.loadContent(
"<div style='width: 100; height: 100; background: green;' " +
"onclick='javaObj.clickLeft();' />"
);
getChildren().add(webView);
}
@Override
protected void layoutChildren(){
double w = getWidth();
double h = getHeight();
layoutInArea(webView, 0, 0, w, h, 0, HPos.CENTER, VPos.CENTER);
// layoutInArea(toolbar, 0, h-toolbarHeight, w, toolbarHeight, 0, HPos.CENTER, VPos.CENTER);
}
}
public class Bridge {
public void clickRight() {
System.out.println("Bridge.clickRight() called");
}
public void clickLeft() throws IOException {
System.out.println("Bridge.clickLeft() called");
WebView webView = new WebView();
WebEngine webEngine = webView.getEngine();
webEngine.getLoadWorker().stateProperty().addListener(
new ChangeListener<Worker.State>() {
public void changed(ObservableValue<? extends Worker.State> p, Worker.State oldState, Worker.State newState) {
if (newState == Worker.State.SUCCEEDED) {
JSObject win = (JSObject) webEngine.executeScript("window");
win.setMember("javaObj", new Bridge());
System.out.println("Bridge.clickLeft(): property Changed of LeftWebView");
}
}
}
);
webEngine.loadContent(
"<div style='width: 200; height: 200; background: blue;' " +
"onclick='javaObj.test2();' />"
);
/*
FXMLLoader fxmlLoader = new FXMLLoader();
Pane p = fxmlLoader.load(getClass().getResource("FXMLDocument.fxml").openStream());
FXMLDocumentController fooController = (FXMLDocumentController) fxmlLoader.getController();
*/
/*
URL location = getClass().getResource("MyController.fxml");
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(location);
Parent root = (Parent) fxmlLoader.load(location.openStream());
// How to get the handler for a specific element of my FXML
*/
}
}
<?import javafx.scene.web.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import demo2.RightWebView?>
<?import demo2.LeftWebView?>
<?import demo2.FXMLDocumentController?>
<AnchorPane fx:controller="demo2.FXMLDocumentController" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8">
<SplitPane dividerPositions="0.4765886287625418" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity"
prefHeight="400.0" prefWidth="600.0" >
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<LeftWebView id="webLeft" fx:id="wvLeftWebView" prefHeight="-1.0" prefWidth="-1.0" onAction="#myCustomAction" />
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<RightWebView id="webRight" fx:id="wvRightWebView" prefHeight="-1.0" prefWidth="-1.0" />
</children>
</AnchorPane>
</items>
</SplitPane>
</AnchorPane>
我可以通过 Java 脚本回调 class Bridge (Bridge.clickLeft()) 中的一个方法,但我不确定如何着手访问另一个方法WebView 并更新它。
我通过其他问题找到了一个简单的解决方案
FXML 文件包含两个网页视图和一个标签(标签只是为了显示一个 JavaFX 控件)
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="webviewlabel.FXMLDocumentController">
<children>
<WebView fx:id="wvSample" layoutX="184.0" layoutY="16.0" prefHeight="200.0" prefWidth="175.0" />
<WebView fx:id="wvAffected" layoutY="39.0" prefHeight="177.0" prefWidth="154.0" />
<Label fx:id="lblSample" text="Label" />
</children>
</AnchorPane>
控制器class包含
public class FXMLDocumentController implements Initializable {
@FXML
private Label lblSample;
@FXML
private WebView wvSample;
private WebEngine webSample ;
@FXML
private WebView wvAffected;
private WebEngine webAffected ;
@FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
}
@Override
public void initialize(URL url, ResourceBundle rb) {
// wvSample = new WebView();
initiateWebSample();
initiateWebAffected();
}
public void initiateWebSample() {
webSample = wvSample.getEngine();
webSample.getLoadWorker().stateProperty().addListener(
new ChangeListener<Worker.State>() {
public void changed(ObservableValue<? extends Worker.State> p, Worker.State oldState, Worker.State newState) {
if (newState == Worker.State.SUCCEEDED) {
JSObject win = (JSObject) webSample.executeScript("window");
win.setMember("javaObj", new Connector(FXMLDocumentController.this));
System.out.println("FXMLDocumentController.initiateWebSample(): Called");
}
}
}
);
webSample.loadContent(
"<div style='width: 50; height: 50; background: yellow;' onclick='javaObj.Connecting();' />"
);
}
public void initiateWebAffected() {
webAffected = wvAffected.getEngine();
webAffected.getLoadWorker().stateProperty().addListener(
new ChangeListener<Worker.State>() {
public void changed(ObservableValue<? extends Worker.State> p, Worker.State oldState, Worker.State newState) {
if (newState == Worker.State.SUCCEEDED) {
JSObject win = (JSObject) webAffected.executeScript("window");
win.setMember("javaObj", new Connector(FXMLDocumentController.this));
System.out.println("FXMLDocumentController.initiateWebAffected(): Called");
}
}
}
);
String strJScript = "<div style='width: 50; height: 50; background: blue;' onclick='javaObj.Connecting();' />" ;
webAffected.loadContent(strJScript);
}
public void setLabelText(String text)
{
System.out.println("FXMLDocumentController.setLabelText(): Called");
lblSample.setText(text);
}
public void changeWebViewAffected(String pstrColor) {
String strJScript = "<div style='width: 50; height: 50; background: "+pstrColor+";' onclick='javaObj.Connecting();' />" ;
webAffected.loadContent(strJScript);
}
}
并且连接class包含要调用的方法
public class Connector {
private final FXMLDocumentController controller ;
public Connector(FXMLDocumentController controller) {
this.controller = controller ;
}
public void Connecting() {
try {
System.out.println("Connector.Connecting(): Called");
controller.setLabelText("Bye World");
controller.changeWebViewAffected("green");
} catch (Exception ex) {
Logger.getLogger(Connector.class.getName()).log(Level.SEVERE, null, ex);
}
}
}