是否有可能在沒有使用FXML的情況下使用帶有JavaFX GUI的控制器。在沒有FXML的情況下使用JavaFX控制器
我注意到FXML文件包含一個fx-controller
屬性來綁定控制器,但我不覺得它是一個簡單的方法來處理它。
有沒有使用FXML文件或JavaFX場景生成器的JavaFX有MVC拱門的任何想法?
是否有可能在沒有使用FXML的情況下使用帶有JavaFX GUI的控制器。在沒有FXML的情況下使用JavaFX控制器
我注意到FXML文件包含一個fx-controller
屬性來綁定控制器,但我不覺得它是一個簡單的方法來處理它。
有沒有使用FXML文件或JavaFX場景生成器的JavaFX有MVC拱門的任何想法?
你的問題還不是特別清楚對我說:你剛纔創建的類,基本上與聽衆一起配合的一切。我不知道這是否有幫助,但這裏有一個簡單的例子,它只有幾個文本字段和一個顯示其總和的標籤。這就是我所說的「經典MVC」:視圖觀察模型並在模型更改時更新UI元素。如果發生事件,它將註冊處理程序與UI元素和委託給控制器:控制器反過來處理輸入(如果需要)並更新模型。
型號:
package mvcexample;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ReadOnlyIntegerWrapper;
import javafx.beans.property.SimpleIntegerProperty;
public class AdditionModel {
private final IntegerProperty x = new SimpleIntegerProperty();
private final IntegerProperty y = new SimpleIntegerProperty();
private final ReadOnlyIntegerWrapper sum = new ReadOnlyIntegerWrapper();
public AdditionModel() {
sum.bind(x.add(y));
}
public final IntegerProperty xProperty() {
return this.x;
}
public final int getX() {
return this.xProperty().get();
}
public final void setX(final int x) {
this.xProperty().set(x);
}
public final IntegerProperty yProperty() {
return this.y;
}
public final int getY() {
return this.yProperty().get();
}
public final void setY(final int y) {
this.yProperty().set(y);
}
public final javafx.beans.property.ReadOnlyIntegerProperty sumProperty() {
return this.sum.getReadOnlyProperty();
}
public final int getSum() {
return this.sumProperty().get();
}
}
控制器:
package mvcexample;
public class AdditionController {
private final AdditionModel model ;
public AdditionController(AdditionModel model) {
this.model = model ;
}
public void updateX(String x) {
model.setX(convertStringToInt(x));
}
public void updateY(String y) {
model.setY(convertStringToInt(y));
}
private int convertStringToInt(String s) {
if (s == null || s.isEmpty()) {
return 0 ;
}
if ("-".equals(s)) {
return 0 ;
}
return Integer.parseInt(s);
}
}
查看:
package mvcexample;
import javafx.geometry.HPos;
import javafx.geometry.Pos;
import javafx.scene.Parent;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.control.TextFormatter.Change;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
public class AdditionView {
private GridPane view ;
private TextField xField;
private TextField yField;
private Label sumLabel;
private AdditionController controller ;
private AdditionModel model ;
public AdditionView(AdditionController controller, AdditionModel model) {
this.controller = controller ;
this.model = model ;
createAndConfigurePane();
createAndLayoutControls();
updateControllerFromListeners();
observeModelAndUpdateControls();
}
public Parent asParent() {
return view ;
}
private void observeModelAndUpdateControls() {
model.xProperty().addListener((obs, oldX, newX) ->
updateIfNeeded(newX, xField));
model.yProperty().addListener((obs, oldY, newY) ->
updateIfNeeded(newY, yField));
sumLabel.textProperty().bind(model.sumProperty().asString());
}
private void updateIfNeeded(Number value, TextField field) {
String s = value.toString() ;
if (! field.getText().equals(s)) {
field.setText(s);
}
}
private void updateControllerFromListeners() {
xField.textProperty().addListener((obs, oldText, newText) -> controller.updateX(newText));
yField.textProperty().addListener((obs, oldText, newText) -> controller.updateY(newText));
}
private void createAndLayoutControls() {
xField = new TextField();
configTextFieldForInts(xField);
yField = new TextField();
configTextFieldForInts(yField);
sumLabel = new Label();
view.addRow(0, new Label("X:"), xField);
view.addRow(1, new Label("Y:"), yField);
view.addRow(2, new Label("Sum:"), sumLabel);
}
private void createAndConfigurePane() {
view = new GridPane();
ColumnConstraints leftCol = new ColumnConstraints();
leftCol.setHalignment(HPos.RIGHT);
leftCol.setHgrow(Priority.NEVER);
ColumnConstraints rightCol = new ColumnConstraints();
rightCol.setHgrow(Priority.SOMETIMES);
view.getColumnConstraints().addAll(leftCol, rightCol);
view.setAlignment(Pos.CENTER);
view.setHgap(5);
view.setVgap(10);
}
private void configTextFieldForInts(TextField field) {
field.setTextFormatter(new TextFormatter<Integer>((Change c) -> {
if (c.getControlNewText().matches("-?\\d*")) {
return c ;
}
return null ;
}));
}
}
應用類:
package mvcexample;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class MVCExample extends Application {
@Override
public void start(Stage primaryStage) {
AdditionModel model = new AdditionModel();
AdditionController controller = new AdditionController(model);
AdditionView view = new AdditionView(controller, model);
Scene scene = new Scene(view.asParent(), 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
這就是我在說的。在沒有FXML的JavaFX上使用「Classical MVC」;謝謝,這很公平 –
我廣泛使用JavaFX並且不使用FXML或scenebuilder。所以我可以保證它可以完成。
下面是我的IDE爲獲得JavaFX主類所做的自動生成的代碼。這將是你的應用程序的根源。然後您將添加到它來創建您的應用程序。
public class NewFXMain extends Application {
@Override
public void start(Stage primaryStage) {
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
System.out.println("Hello World!");
}
});
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
感謝您的回答,但我想知道的是如何將控制器綁定到沒有FXML的視圖,因爲我希望它作爲MVC 3層 –
@HassamAbdelillah有什麼看法?如果你不使用FXML,那麼沒有什麼可以綁定的。您只需將來自UI組件的調用直接傳遞給控制器組件即可。當你創建組件時,你將他們的動作綁定到代碼中的控制器動作上,所以在這個例子中沒有什麼可綁定的。 FXML只需要該方法。你可以在Jose的答案中看到綁定到控件的動作。 – ManoDestra
ÿ您不必使用FXML或SceneBuilder。您可以簡單地自己創建對象,並將它們自己添加到場景/舞臺中。關於如何實施它完全是開放的。我已經實現了一個屏幕管理庫,它可以處理FXML或手動創建的屏幕。它可以完成:) – ManoDestra