当前位置: 首页 > 知识库问答 >
问题:

使用Javascript回调方法更改JavaFX标签

边明煦
2023-03-14
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.web.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="webviewlabel.FXMLDocumentController">
   <children>
      <VBox prefHeight="200.0" prefWidth="100.0">
         <children>
            <Label id="lblSample" fx:id="lblSample" text="Sample Label" />
            <WebView fx:id="wvSample" prefHeight="200.0" prefWidth="200.0" />
         </children>
      </VBox>
   </children>
</AnchorPane>
public class FXMLDocumentController implements Initializable {

    @FXML
    private Label lblSample;

    @FXML
    private WebView wvSample;
    private WebEngine webEngine ;

    @FXML
    private void handleButtonAction(ActionEvent event) {
        System.out.println("You clicked me!");    
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // wvSample = new WebView();
        initiateWeb();
    }   

    public void initiateWeb() {
        webEngine = wvSample.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 Connector());      
                        System.out.println("FXMLDocumentController.initialize(): Called");
                    }
                }
            }
        );        
        webEngine.loadContent(
            "<div style='width: 50; height: 50; background: yellow;' onclick='javaObj.Connecting();' />"
        );
    }

    public void setLabelText(String text)
    {
        System.out.println("FXMLDocumentController.setLabelText(): Called");
        lblSample.setText(text);
    }    
}
public class Connector {    
    public void Connecting() {
        try {
            System.out.println("Connector.Connecting(): Called");
            /*
            FXMLLoader loader = new FXMLLoader(FXMLDocumentController.class.getResource("FXMLDocument.fxml"));
            loader.load();
            FXMLDocumentController controller = (FXMLDocumentController) loader.getController();
            */
            // controller.setLabelText("Bye World");
        } catch (Exception ex) {
            Logger.getLogger(Connector.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

从问题的答案中,我可以理解FXMLDocumentController可以作为参数传递,但我不确定如何在通过javascript回调访问控制器时访问它。

共有1个答案

鄢翰藻
2023-03-14

连接器类中定义一个字段和一个初始化它的构造函数:

public class Connector {

    private final FXMLDocumentController controller ;

    public Connector(FXMLDocumentController controller) {
        this.controller = controller ;
    }

    // ...
}

然后可以在connecting()方法中直接引用控制器:

public void connecting() {
    // ...

    controller.setLabelText("Bye World");
    // ...
}

就像你之前想做的那样。

现在您只需使用对控制器的引用构造连接器:

public class FXMLDocumentController {

    // ...

    public void initiateWeb() {
        // ...

        webEngine.getLoadWorker().stateProperty().addListener(
            new ChangeListener<State>() {
                // ...

                win.setMember("javaObj", new Connector(FXMLDocumentController.this));
                // ...
            }
        );
    }
    // ...
}  

作为一个变体,在Java8中,不是在连接器类中存储对控制器的引用,而是只存储处理消息的函数:

public class Connector {

    private final Consumer<String> messageUpdater ;

    public Connector(Consumer<String> messageUpdater) {
        this.messageUpdater = messageUpdater ;
    }

    // ...

    public void connecting() {
        // ...
        messageUpdater.accept("Bye world");
        // ...
    }
}

然后实例化连接器

webEngine.getLoadWorker().stateProperty().addListener((obs, oldState, newState) -> {
    if (newState == Worker.State.SUCCEEDED) {
        JSObject win = (JSObject) webEngine.executeScript("window");
        win.setMember("javaObj", new Connector(this::setLabelText));      
        System.out.println("FXMLDocumentController.initialize(): Called");
    }
});
 类似资料:
  • 问题内容: 为什么以下内容对我不起作用? 问题答案: 因为您的脚本在运行之前运行,所以标签存在于页面中(在DOM中)。可以将脚本放在标签后,或者等待文档完全加载(使用OnLoad函数) 这行不通: 这将起作用: 此示例(jsfiddle链接)维护顺序(首先是脚本,然后是标签),并使用onLoad:

  • 我正在尝试为用Java编写的应用程序制作GUI。 我用Scene Builder制作了fxml文档,正确设置了fx: id,现在我正在尝试对表单进行简单的更改。 我的DocumentController: 我的外汇主文件: 我现在想要的一切,都是将LabelData设置为实际时间戳,但当我运行FX主文件时,什么都不会发生。有人能帮我吗? 谢谢你保罗 更新时间: 我的整个FXML文档: 我想要的一切

  • 我需要更改JavaFX中标签的锚点。我将锚点描述为选择来翻译底层节点的点。默认情况下,锚点似乎是左上角。 我试图通过如下描述的附加翻译来解决这个问题: 代码应转换标签,使其像右下角的锚点一样工作。这不起作用,因为在我执行代码时,标签的边界框是[minX:0.0,minY:0.0,minZ:0.0,宽度:-1.0,高度:-1.0,深度:0.0,maxX:-1.0,maxY:-1.0,maxZ:0.0

  • 使用Angular 2更改值时,如何调用方法? 我尝试使用ng change,但没有成功。

  • 下面是一个简单对话框的示例代码: 下面是一些活动代码: 代码与您所看到的引用大致相同。问题是,一旦您改变了方向,当显示对话框时,它就停止了预期的工作-->由于活动生命周期的原因,活动和对话框都被重新构建,并且对话框现在没有对重新构建的新活动的正确引用。 致以最诚挚的问候