我试图制作一个可以用于未来项目的通用类。它只是一个简单的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()启动的应用程序线程
答案 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()
创建的实例。所以:
如果要在应用程序启动之前自定义应用程序的参数,可以覆盖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属性)。否则,请应用上述更改。
如果要在应用程序启动后更改参数,则需要提供对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)
您发布的代码不起作用的原因是(static
)launch(...)
方法为您创建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());