2

私はJavaFXプログラミングの初心者です。ここの例で説明されているような単純なログインページを持つアプリケーションがあり、stringPropertyをactiontarget要素に追加します。したがって、アクションターゲット内でテキストが変更された場合、FXMLLoaderからロードして画面にディップスレイするために、内部にWebビューを含む新しいFXMLファイルが必要です。以下は私が得る例外です。Webビューがなくても、他のfxmlファイルを問題なくロードできます。事前に感謝します。以下のコードサンプル例外:

java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-3
at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:237)
at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:397)
at com.sun.webpane.sg.prism.InvokerImpl.checkEventThread(InvokerImpl.java:33)
at com.sun.webpane.platform.WebPage.<init>(WebPage.java:189)
at com.sun.webpane.sg.ImplementationManager.createPage(ImplementationManager.java:57)
at com.sun.webpane.sg.ImplementationManager.createPage(ImplementationManager.java:51)
at javafx.scene.web.WebEngine.<init>(WebEngine.java:704)
at javafx.scene.web.WebEngine.<init>(WebEngine.java:691)
at javafx.scene.web.WebView.<init>(WebView.java:245)
at student.WebBrowser.<init>(WebBrowser.java:31)
at Login.Login.replaceSceneContent(Login.java:171)
at Login.Login.access$000(Login.java:66)
at Login.Login$2.changed(Login.java:143)
at Login.Login$2.changed(Login.java:137)
at com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:196)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:100)
at javafx.beans.property.StringPropertyBase.fireValueChangedEvent(StringPropertyBase.java:121)
at javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:128)
at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:161)
at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:67)
at javafx.scene.text.Text.setText(Text.java:188)
at Login.Client.run(Client.java:66)

最初に私のリスナー:

// Add change listener
    sp.addListener(new ChangeListener<String>() {
        @Override
        public void changed(ObservableValue<? extends String> ov, String t, String t1) {

            if(t1.equalsIgnoreCase("user authenticated successfully")){
                try {
                    replaceSceneContent(cb.getSelectionModel().getSelectedItem().toString()+".fxml",primaryStage);
                    System.out.println("everything ok");
                } catch (Exception ex) {
                    System.out.println("something went wrong");
                    ex.printStackTrace();
                }
            }
        }
    });

2番目の私のメソッド:replaceSceneContent(String fxml、Stage stage)

private Parent replaceSceneContent(String fxml, Stage stage) throws Exception {
    Parent page = (Parent) FXMLLoader.load(getClass().getResource("/FXML_Files/"+fxml), null, new JavaFXBuilderFactory());      
    Scene scene = stage.getScene();
    if (scene == null) {
        scene = new Scene(page, 700, 450);
        stage.setScene(scene);
    } else {
        stage.getScene().setRoot(page);
    }
    if(fxml.equalsIgnoreCase("Student.fxml")){
        Pane spane = (Pane) page.lookup("#pane");
        WebBrowser wb = new WebBrowser();           
        spane.getChildren().add(wb);            
    }
    return page;
}

そして、NetBeans7.2の例に似た私のWebBrowserクラス:

public class WebBrowser extends Pane {

    public WebBrowser() {

        WebView view;
        final WebEngine eng;    
        view = new WebView();
        view.setMinSize(10, 10);
        view.setPrefSize(500, 400);
        eng = view.getEngine();
        eng.load("http://www.oracle.com/us/index.html");

        VBox.setVgrow(this, Priority.ALWAYS);
        setMaxWidth(Double.MAX_VALUE);
        setMaxHeight(Double.MAX_VALUE);

        final TextField locationField = new TextField("http://www.oracle.com/us/index.html");
        locationField.setMaxHeight(Double.MAX_VALUE);
        Button goButton = new Button("Go");
        goButton.setDefaultButton(true);
        EventHandler<ActionEvent> goAction = new EventHandler<ActionEvent>() {
            @Override public void handle(ActionEvent event) {
                eng.load(locationField.getText().startsWith("http://") ? locationField.getText() :
                        "http://" + locationField.getText());
            }
        };

        goButton.setOnAction(goAction);
        locationField.setOnAction(goAction);
        eng.locationProperty().addListener(new ChangeListener<String>() {
            @Override public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                locationField.setText(newValue);
           }
        });
        GridPane grid = new GridPane();
        ButtonsEvents be = new ButtonsEvents();
        TilePane tp = be;
        tp.setAlignment(Pos.CENTER);
        grid.setVgap(5);
        grid.setHgap(5);
        GridPane.setConstraints(locationField, 0, 0, 1, 1, HPos.CENTER, VPos.CENTER, Priority.ALWAYS, Priority.SOMETIMES);
        GridPane.setConstraints(goButton,1,0);
        GridPane.setConstraints(view, 0, 1, 2, 1, HPos.CENTER, VPos.CENTER, Priority.ALWAYS, Priority.ALWAYS);
        GridPane.setConstraints(tp, 0, 2, 2, 1, HPos.CENTER, VPos.CENTER, Priority.ALWAYS, Priority.NEVER);
        grid.getColumnConstraints().addAll(
                new ColumnConstraints(100, 100, Double.MAX_VALUE, Priority.ALWAYS, HPos.CENTER, true),
                new ColumnConstraints(40, 40, 40, Priority.ALWAYS, HPos.CENTER, true)
        );
        grid.getChildren().addAll(locationField, goButton,view, tp);
        getChildren().add(grid);
    }

    @Override 
    protected void layoutChildren() {
        List<Node> managed = getManagedChildren();
        double width = getWidth();
        double height = getHeight();
        double top = getInsets().getTop();
        double right = getInsets().getRight();
        double left = getInsets().getLeft();
        double bottom = getInsets().getBottom();
        for (int i = 0; i < managed.size(); i++) {
            Node child = managed.get(i);
            layoutInArea(child, left, top,
                           width - left - right, height - top - bottom,
                           0, Insets.EMPTY, true, true, HPos.CENTER, VPos.CENTER);
        }
    }
  }
4

1 に答える 1

0

例外に記載されているように、JavaFX シーン グラフの変更は、JavaFX アプリケーション スレッドでのみ行うことができます。コードがこのスレッドで実行されることを確認するには、次のことを試してください。

Platform.runLater(new Runnable() {
             @Override
             public void run() {
                 // This method is invoked on JavaFX thread
                 replaceSceneContent(cb.getSelectionModel().getSelectedItem().toString()+".fxml",primaryStage);
             }
         });

javafx マネージャーは、将来のある時点でこのコードを正しいスレッドで実行します。

詳細: http://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm

于 2012-10-31T08:47:37.540 に答える