Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaFXWebView不适用于SpringBootMaven_Java_Spring Boot_Javafx_Javafx Webengine_Javafx Webview - Fatal编程技术网

JavaFXWebView不适用于SpringBootMaven

JavaFXWebView不适用于SpringBootMaven,java,spring-boot,javafx,javafx-webengine,javafx-webview,Java,Spring Boot,Javafx,Javafx Webengine,Javafx Webview,我已经用scene builder创建了Spring boot JavaFX应用程序。在FXML文件中添加WebView组件时,出现以下错误: Caused by: javafx.fxml.LoadException: /C:/Users/pdhasar/WebProject/standalone-app/target/classes/WebView.fxml:12 at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader

我已经用scene builder创建了Spring boot JavaFX应用程序。在FXML文件中添加WebView组件时,出现以下错误:

Caused by: javafx.fxml.LoadException: 
/C:/Users/pdhasar/WebProject/standalone-app/target/classes/WebView.fxml:12

    at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2605)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2583)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2445)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2413)
    at com.web.view.WebViewApplication.init(WebViewApplication.java:29)
    at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:841)
    ... 3 more
Caused by: java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    at javafx.fxml.JavaFXBuilder$ObjectBuilder.build(JavaFXBuilderFactory.java:278)
    at javafx.fxml.FXMLLoader$ValueElement.processEndElement(FXMLLoader.java:759)
    at javafx.fxml.FXMLLoader.processEndElement(FXMLLoader.java:2827)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2536)
    ... 7 more
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
    at javafx.fxml.JavaFXBuilder$ObjectBuilder.build(JavaFXBuilderFactory.java:270)
    ... 10 more
Caused by: java.lang.IllegalStateException: Not on FX application thread; currentThread = JavaFX-Launcher
    at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:204)
    at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:438)
    at javafx.scene.web.WebEngine.checkThread(WebEngine.java:1182)
    at javafx.scene.web.WebEngine.<init>(WebEngine.java:822)
    at javafx.scene.web.WebEngine.<init>(WebEngine.java:811)
    at javafx.scene.web.WebView.<init>(WebView.java:271)
    at javafx.scene.web.WebViewBuilder.build(WebViewBuilder.java:60)
    ... 21 more
2019-10-07 14:00:12.979  INFO 14680 --- [       Thread-6] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@7f904074: startup date [Mon Oct 07 14:00:10 IST 2019]; root of context hierarchy
WebViewController:

package com.web.view.controller;

import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import org.springframework.stereotype.Controller;

@Controller
public class WebViewController {

    @FXML private WebView webView;
    private WebEngine webEngine;

    @FXML
    private void handleWebViewButtonAction(ActionEvent event) {
        webEngine = webView.getEngine();
        webEngine.load("https://www.google.co.in");
    }
}
FXML:



spring似乎正在尝试访问WebView,javafx中有一个限制,不允许spring访问它。有没有办法让WebView与spring boot一起工作。谁能帮我解决这个问题。

我终于找到了解决办法。在我将下面的代码添加到init方法中之后,它就工作了

Platform.runLater(() -> { ... });

JavaFX线程的背景

JavaFX系统的一个限制是,并非所有控件都可以脱离JavaFX应用程序线程构造。当给定控件或UI元素出现这种情况时,其文档会对此进行注释

特别是,各国的文件:

必须仅从FX线程创建和访问WebView对象

JavaFX应用程序的
init()
方法不在JavaFX应用程序线程上运行。在我的环境(OSX,JavaFX13)中,JavaFX应用程序的
init()
方法由一个名为“JavaFXLauncher”的线程调用。如果将以下代码放入
init()
,可以看出:

将相同的代码放在
start()
方法中表明它运行在另一个名为“JavaFX应用程序线程”的线程上。这是创建WebView的正确线程

FXML加载程序基于FXML文件构造对象。如果您试图从JavaFX应用程序线程加载FXML,并且它包含必须在JavaFX应用程序线程上构造的某种控件,那么您将失败(如您所见)。大多数控件都可以在JavaFX线程之外构建,所以大多数情况下这不是问题。但是,
WebView
必须在JavaFX应用程序线程上构建,因此您不能在JavaFX应用程序线程中加载带有
WebView
的FXML文档

start()
init()
加载包含WebView引用的FXML

解决方案是将加载包含WebView的FXML的位置从
init()
方法移动到
start()
方法(由kleopatra在注释中建议),如下所示:

import javafx.fxml.FXMLLoader;
import javafx.geometry.Rectangle2D;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Screen;
import javafx.stage.Stage;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan("com.web.view")
public class WebViewApplication extends Application {

    private ConfigurableApplicationContext context;
    private Parent rootNode;

    @Override
    public void init() throws Exception {
        SpringApplicationBuilder builder = new SpringApplicationBuilder(WebViewApplication.class);
        context = builder.run(getParameters().getRaw().toArray(new String[0]));
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("/WebView.fxml"));
        loader.setControllerFactory(context::getBean);
        rootNode = loader.load();

        Rectangle2D visualBounds = Screen.getPrimary().getVisualBounds();
        double width = visualBounds.getWidth();
        double height = visualBounds.getHeight();

        primaryStage.setScene(new Scene(rootNode, width, height));
        primaryStage.centerOnScreen();
        primaryStage.show();
    }

    @Override
    public void stop() throws Exception {
        context.close();
    }
}
不相关的设计建议

另外,我建议不要将JavaFX应用程序设置为Spring应用程序

相反,为Spring应用程序创建一个单独的类:

package com.web.view;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Rectangle2D;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Screen;
import javafx.stage.Stage;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan("com.web.view")
public class WebViewApplication extends Application {

    private ConfigurableApplicationContext context;
    private Parent rootNode;

    @Override
    public void init() throws Exception {
        SpringApplicationBuilder builder = new SpringApplicationBuilder(WebViewApplication.class);
        context = builder.run(getParameters().getRaw().toArray(new String[0]));
        FXMLLoader loader = new FXMLLoader(getClass().getResource("/WebView.fxml"));
        loader.setControllerFactory(context::getBean);
        rootNode = loader.load();
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        Rectangle2D visualBounds = Screen.getPrimary().getVisualBounds();
        double width = visualBounds.getWidth();
        double height = visualBounds.getHeight();

        primaryStage.setScene(new Scene(rootNode, width, height));
        primaryStage.centerOnScreen();
        primaryStage.show();
    }

    @Override
    public void stop() throws Exception {
        context.close();
    }
}
@SpringBootApplication
public class MySpringApplication {
    // spring application implementation.
}
并让您的JavaFX应用程序调用
run()
在已使用特定spring应用程序类初始化的
SpringApplicationBuilder
实例上运行(即在您的JavaFX
init()
方法中有):

否则,您可能会在运行时创建两个JavaFX应用程序实例(一个由JavaFX应用程序创建),另一个由Spring应用程序运行程序创建,这可能会造成混淆。另外,通过将两者分离,您可以通过更强的关注点分离获得更好的设计,JavaFX应用程序负责处理JavaFX应用程序生命周期事件,而Spring应用程序负责处理Spring生命周期事件


然后,您可以完全独立于JavaFX应用程序启动和测试spring应用程序,这将使代码的测试和分析更加容易。

hmm。。。想知道为什么要使用init方法(该方法被记录为从fx应用程序线程调用),而不是将其包装到runlater中(将其排队以便在fx应用程序线程上执行),您可以将其移动到start(该方法被记录为在fx线程上调用),或者为什么不这样做?它在init中失败,而不是在start中失败。spring线程正在尝试初始化和加载元素,但失败。Praveen,没有“spring线程”。在我的环境(OSX,JavaFX13)中,JavaFX应用程序的
init()
方法由名为
JavaFXLauncher
的线程调用。从
init()
=>
System.out.println(“线程名称:”+Thread.currentThread().getName())中的以下代码可以看出:
import javafx.fxml.FXMLLoader;
import javafx.geometry.Rectangle2D;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Screen;
import javafx.stage.Stage;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan("com.web.view")
public class WebViewApplication extends Application {

    private ConfigurableApplicationContext context;
    private Parent rootNode;

    @Override
    public void init() throws Exception {
        SpringApplicationBuilder builder = new SpringApplicationBuilder(WebViewApplication.class);
        context = builder.run(getParameters().getRaw().toArray(new String[0]));
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("/WebView.fxml"));
        loader.setControllerFactory(context::getBean);
        rootNode = loader.load();

        Rectangle2D visualBounds = Screen.getPrimary().getVisualBounds();
        double width = visualBounds.getWidth();
        double height = visualBounds.getHeight();

        primaryStage.setScene(new Scene(rootNode, width, height));
        primaryStage.centerOnScreen();
        primaryStage.show();
    }

    @Override
    public void stop() throws Exception {
        context.close();
    }
}
@SpringBootApplication
public class MySpringApplication {
    // spring application implementation.
}
SpringApplicationBuilder builder = new SpringApplicationBuilder(
    MySpringApplication.class
);
context = builder.run(
    getParameters().getRaw().toArray(new String[0])
);