2016-04-26 136 views
1

是否有可能在沒有使用FXML的情況下使用帶有JavaFX GUI的控制器。在沒有FXML的情況下使用JavaFX控制器

我注意到FXML文件包含一個fx-controller屬性來綁定控制器,但我不覺得它是一個簡單的方法來處理它。

有沒有使用FXML文件或JavaFX場景生成器的JavaFX有MVC拱門的任何想法?

+0

ÿ您不必使用FXML或SceneBuilder。您可以簡單地自己創建對象,並將它們自己添加到場景/舞臺中。關於如何實施它完全是開放的。我已經實現了一個屏幕管理庫,它可以處理FXML或手動創建的屏幕。它可以完成:) – ManoDestra

回答

6

你的問題還不是特別清楚對我說:你剛纔創建的類,基本上與聽衆一起配合的一切。我不知道這是否有幫助,但這裏有一個簡單的例子,它只有幾個文本字段和一個顯示其總和的標籤。這就是我所說的「經典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); 
    } 
} 
+0

這就是我在說的。在沒有FXML的JavaFX上使用「Classical MVC」;謝謝,這很公平 –

2

我廣泛使用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); 
} 

} 
+0

感謝您的回答,但我想知道的是如何將控制器綁定到沒有FXML的視圖,因爲我希望它作爲MVC 3層 –

+2

@HassamAbdelillah有什麼看法?如果你不使用FXML,那麼沒有什麼可以綁定的。您只需將來自UI組件的調用直接傳遞給控制器​​組件即可。當你創建組件時,你將他們的動作綁定到代碼中的控制器動作上,所以在這個例子中沒有什麼可綁定的。 FXML只需要該方法。你可以在Jose的答案中看到綁定到控件的動作。 – ManoDestra

相關問題