User interface Javafx使gui显示与基础数据保持同步
我对Javafx和一般的GUI编程不熟悉。我正在开发一个应用程序,如标签需要更新,只要变量有任何变化。 我已经使用了属性和绑定,但是只有在我关闭并重新打开窗口时才能看到更改。 更清楚地说,我并不是说如果用户在文本文件中写入内容,就要更改标签,这样我就没有问题了。但标签中包含整数或字符串,并且实际上没有触发器 因此,我的一般问题是:当某些内容发生变化时,如何更新应用程序中的某些内容。 我重新创建了一个简单的示例,这样也许你们可以理解我想问的问题(对不起,不是母语人士),但不必选择关闭或重新打开窗口 主要内容: 数据模型:User interface Javafx使gui显示与基础数据保持同步,user-interface,javafx,properties,binding,User Interface,Javafx,Properties,Binding,我对Javafx和一般的GUI编程不熟悉。我正在开发一个应用程序,如标签需要更新,只要变量有任何变化。 我已经使用了属性和绑定,但是只有在我关闭并重新打开窗口时才能看到更改。 更清楚地说,我并不是说如果用户在文本文件中写入内容,就要更改标签,这样我就没有问题了。但标签中包含整数或字符串,并且实际上没有触发器 因此,我的一般问题是:当某些内容发生变化时,如何更新应用程序中的某些内容。 我重新创建了一个简单的示例,这样也许你们可以理解我想问的问题(对不起,不是母语人士),但不必选择关闭或重新打开窗口
public class DataModel {
public static IntegerProperty number = new SimpleIntegerProperty(0);
public static void getNumber(int number) {
DataModel.number.set(number);
System.out.println("DataModel " + number);
}
}
请查看注释以遵循对代码所做的更改。要运行,请将整个代码复制到
Test.java
并运行:
import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Test extends Application{
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
Stage window = primaryStage;
window.setTitle("Configuration");
FlowPane numberOfDirPane = new FlowPane();
Label dirLabel = new Label("Number of Directories: ");
//construct a DataModel
DataModel dataModel = new DataModel();
//in the original code this label was constructed but never added to a panel
Label numberOfDirLabel = new Label("");
//bind label to the data model
numberOfDirLabel.textProperty().bind( dataModel.numberProperty().asString());
//add numberOfDirLabel to the panel
numberOfDirPane.getChildren().addAll(dirLabel, numberOfDirLabel);
numberOfDirPane.setAlignment(Pos.CENTER);
FlowPane editDir = new FlowPane();
Label editLabel = new Label("Edit Number of Directories: ");
TextField numberDirText = new TextField();
numberDirText.setMaxWidth(50);
Button editDirNumberButton = new Button("Confirm");
editDirNumberButton.setOnAction(e -> {
dataModel.setNumber(Integer.parseInt(numberDirText.getText()));
});
editDir.getChildren().addAll(editLabel, numberDirText, editDirNumberButton);
editDir.setAlignment(Pos.CENTER);
editDir.setHgap(40);
//to demonstrate the problem the following Flowpane is not needed
//and should be removed. see https://stackoverflow.com/help/minimal-reproducible-example
FlowPane buttons = new FlowPane();
Button confirmEditButton = new Button("Confirm");
Button closeButton = new Button("Close");
closeButton.setOnAction(e -> window.close());
buttons.getChildren().addAll(confirmEditButton, closeButton);
buttons.setAlignment(Pos.CENTER);
buttons.setHgap(20);
VBox layout = new VBox(20);
layout.getChildren().addAll(numberOfDirPane, editDir, buttons);
layout.setAlignment(Pos.CENTER);
Scene scene = new Scene(layout, 500, 300);
window.setScene(scene);
window.show();
}
}
class DataModel {
//there is no need to use static fieilds and methods here
private final IntegerProperty numberProperty = new SimpleIntegerProperty(0);
public void setNumber(int number) {
numberProperty.set(number);
}
//add a getter
public IntegerProperty numberProperty() {
return numberProperty;
}
}
一件可怕的事情是,你真的想在每次触发动作时保持绑定吗<代码>numberOfDirLabel.textProperty().bind(DataModel.number.asString())
DataModel.getNumber
看起来应该是一个setter。另外,我相信您应该有方法getNumberProperty
。这将允许您创建绑定。DataModel.number.set(number)
在JavaFX
中是非常糟糕的做法,可能应该避免。我建议你学习@Jame\D答案。无论你做什么,都不要使用静态范围!不要使用带有副作用的工具getter。。(这可能是@Sedrick已经指出的:)总的来说,您的代码看起来需要完成两个关于java语言基础知识和javafx基础知识的教程……一旦值发生变化,标签就会更新。您没有看到它的更改,因为您尚未将其添加到场景中。
import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Test extends Application{
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
Stage window = primaryStage;
window.setTitle("Configuration");
FlowPane numberOfDirPane = new FlowPane();
Label dirLabel = new Label("Number of Directories: ");
//construct a DataModel
DataModel dataModel = new DataModel();
//in the original code this label was constructed but never added to a panel
Label numberOfDirLabel = new Label("");
//bind label to the data model
numberOfDirLabel.textProperty().bind( dataModel.numberProperty().asString());
//add numberOfDirLabel to the panel
numberOfDirPane.getChildren().addAll(dirLabel, numberOfDirLabel);
numberOfDirPane.setAlignment(Pos.CENTER);
FlowPane editDir = new FlowPane();
Label editLabel = new Label("Edit Number of Directories: ");
TextField numberDirText = new TextField();
numberDirText.setMaxWidth(50);
Button editDirNumberButton = new Button("Confirm");
editDirNumberButton.setOnAction(e -> {
dataModel.setNumber(Integer.parseInt(numberDirText.getText()));
});
editDir.getChildren().addAll(editLabel, numberDirText, editDirNumberButton);
editDir.setAlignment(Pos.CENTER);
editDir.setHgap(40);
//to demonstrate the problem the following Flowpane is not needed
//and should be removed. see https://stackoverflow.com/help/minimal-reproducible-example
FlowPane buttons = new FlowPane();
Button confirmEditButton = new Button("Confirm");
Button closeButton = new Button("Close");
closeButton.setOnAction(e -> window.close());
buttons.getChildren().addAll(confirmEditButton, closeButton);
buttons.setAlignment(Pos.CENTER);
buttons.setHgap(20);
VBox layout = new VBox(20);
layout.getChildren().addAll(numberOfDirPane, editDir, buttons);
layout.setAlignment(Pos.CENTER);
Scene scene = new Scene(layout, 500, 300);
window.setScene(scene);
window.show();
}
}
class DataModel {
//there is no need to use static fieilds and methods here
private final IntegerProperty numberProperty = new SimpleIntegerProperty(0);
public void setNumber(int number) {
numberProperty.set(number);
}
//add a getter
public IntegerProperty numberProperty() {
return numberProperty;
}
}