如何在javafx应用程序实例化后更改变量值?

时间:2015-08-07 04:20:39

标签: java javafx

我试图制作一个可以用于未来项目的通用类。它只是一个简单的javafx浏览器。我遇到的问题是我希望能够动态地更改某些属性(在实例化时)。我添加了一些简单的setter,希望它能够胜任这项工作,但是它们不起作用。有没有办法在start()执行后更改变量?

班级代码:

package rob.rushton;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;

public class RushBrowser extends Application {

    public RushBrowser() {}

    private String url = "www.google.com";
    private final String fullUrl = "http://" + url;
    String title = "Simple Browser";
    private int height = 750;
    private int width = 750;

    public void openBrowser() {
        launch();
    }

    public void setURL(String u) {
        url = u;
    }

    public void setHeightWidth(int h, int w) {
        height = h;
        width = w;
    }

    public void setTitle(String t) {
        title = t;
    }

    @Override
     public void start(Stage stage) {
        stage.setTitle(this.title);
        BorderPane pane = new BorderPane();
        Scene scene = new Scene(pane, width, height);
        WebView browser = new WebView();
        WebEngine engine = browser.getEngine();
        engine.load(fullUrl);
        pane.setCenter(browser);
        stage.setScene(scene);
        stage.show();
    }
}

我试图像这样运行它:

package rushtest;

import rob.rushton.RushBrowser;

public class RushTest {

    public static void main(String[] args) {
        RushBrowser rush = new RushBrowser();
        rush.setTitle("Test Title");
        rush.setURL("www.github.com");
        rush.setHeightWidth(1000, 1000);
        rush.openBrowser();
    }    
}

编辑:(8/9/15)下面列出的建议都没有奏效:(问题是我不知道如何访问由launch()启动的应用程序线程

2 个答案:

答案 0 :(得分:1)

您应该使这些属性成为真正的JavaFX属性,或者将其setter委托更新为实际的UI对象。一些粗略的代码 - 只显示相关部分:

真正的JavaFX属性的案例:

public class RushBrowser extends Application {

    ...
    private StringProperty titleProperty = new SimpleStringProperty("Simple Browser");
    ...

    public void setTitle(String t) {
        titleProperty.set(t);
    }

    @Override
     public void start(Stage stage) {
        stage.titleProperty().bind(this.titleProperty);
        ...
    }
}

授权案例 - 您还必须保留Stage

的参考
public class RushBrowser extends Application {

    ...
    private Stage primaryStage;
    // no need to keep the title member variable
    ...

    public void setTitle(String t) {
        primaryStage.setTitle(t);
    }

    @Override
    public void start(Stage stage) {
        this.primaryStage = stage;
        ...
    }
}

修改

根据James_D的评论,还有另一个问题:main方法没有引用Application.launch()创建的实例。所以:

  1. 如果要在应用程序启动之前自定义应用程序的参数,可以覆盖Application.init()

    public class SpecialRushBrowser extends RushBrowser {
        public void init() {
            this.setTitle("Test Title");
            ...
        }
    }
    

    或者来自测试代码:

    public class RushTest {
        static class TestRushBrowser extends RushBrowser {
            public void init() {
                super.init(); // just in case
                this.setTitle("Test Title");
                ...
            }
        }
    
        public static void main(String[] args) {
            TestRushBrowser.launch();
        }
    }
    

    如果以后不需要修改这些参数,可以按原样保留代码(即不需要JavaFX属性)。否则,请应用上述更改。

  2. 如果要在应用程序启动后更改参数,则需要提供对RushBrowser创建的Application.launch()实际实例的引用,该实例将执行更改。一个简单但的方法是使用全局变量:

    public class RushBrowser extends Application {
        public static RushBrowser INSTANCE;
    
        public void init() {
            INSTANCE = this;
        }
    
        ...
    }
    

    然后从launch()之后运行的任何代码:

    RushBrowser.INSTANCE.setTitle(...);
    ...
    

    由于全局状态通常很危险,如果应用程序变得更复杂,您可能希望尝试使用依赖注入框架。即使使用DI也可能会变得棘手,因为主类仍然是在DI框架之外的JavaFX中创建的 - 但这是另一个故事。

    您需要再次应用编辑上方的更改。

答案 1 :(得分:0)

您发布的代码不起作用的原因是(staticlaunch(...)方法为您创建Application子类的新实例,然后调用它的 start(...)方法。因此,调用所有setXXX(...)方法的实例不是调用start(...)方法的实例。

您将可重用部分定义在错误的位置:Application子类本身不可重用。您应该将start()子类中的Application方法视为常规JavaFX应用程序中main()方法的等效方法。

所以:

public class RushBrowser {

    private final BorderPane view ;

    private String url = "www.google.com";
    private final String fullUrl = "http://" + url;
    private String title = "Simple Browser";
    private int height = 750;
    private int width = 750;

    private WebEngine engine ;

    public RushBrowser() {
        WebView browser = new WebView();
        view = new BorderPane(browser);
        engine = browser.getEngine();
    }

    public Node getView() {
        return view ;
    }

    public void show(Stage stage) {
        Scene scene = new Scene(view, width, height);
        stage.setScene(scene);
        stage.show();
    }

    public void show() {
        show(new Stage());
    }

    public void setURL(String u) {
        url = u;
    }

    public void setHeightWidth(int h, int w) {
        height = h;
        width = w;
        view.setPrefSize(w, h);
    }

    public void setTitle(String t) {
        title = t;
        Scene scene = view.getScene();
        if (scene != null) {
            Window window = scene.getWindow();
            if (window instanceof Stage) {
                ((Stage)window).setTitle(title);
            }
        } 
    }
}

然后用Application子类测试它:

public class RushBrowserTest extends Application {

    @Override
    public void start(Stage primaryStage) {
        RushBrowser rush = new RushBrowser();
        rush.setTitle("Test Title");
        rush.setURL("www.github.com");
        rush.setHeightWidth(1000, 1000);
        rush.show(primaryStage);
    }

    public static void main(String[] args) { launch(args); }
}

当然你可以在其他地方使用它。作为一个任意的例子:

TabPane tabPane = ... ;

RushBrowser rush = new RushBrowser();
rush.setURL("www.github.com");
Tab tab = new Tab();
tab.setContent(rush.getView());