0

I`m trying to develop a javafx project in such a manner that the business logic and the view are seperated. Frankly, I don´t know if i realised it right.

My idea was to create a class view. Simplified it looks like this:

public class View extends Application {

    private Pane screen = new Pane();

    private Rectangle rect;

    private Scene scene = new Scene(screen, 500, 500);


    public View(){
        rect = new Rectangle(10, 10, 100, 100);
        rect.setFill(Color.WHITE);
        rect.setStroke(Color.BLACK);
        screen.getChildren().add(rect);
    }

    @Override
    public void start(Stage primaryStage) {

        primaryStage.setTitle("Rectangles");
        primaryStage.setScene(scene);
        primaryStage.show();

    }

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

    public void setColor() {
        rect.setFill(Color.BROWN);
    }

}

Objects of that class can be created and used in this way in the main method of another class including the bussiness logic:

View foo = new View();
foo.main(null);

Unfortunately, I can´t change its attributes afterwards. Therefore, this statement doesn´t have any effect.

foo.setColor();

Like I said, maybe this is a wrong approach. I´m not very familiar with javafx, so please indulge me.

  • You say you want to separate view and logic, but you have only one class here. If you extend Application this class is your Main.class and your app will start with it. You do not instantiate it from any other class! Where is your logic-part? – Tobi Oct 18 '15 at 10:17
  • I´m sorry, I omitted the whole logic part. The statements below the class should be executed in the main method of another class (this class includes the bussiness logic, which is irrelevant her). – user3803086 Oct 18 '15 at 10:30
  • Does your logic class have a main method too? – Tobi Oct 18 '15 at 10:38
  • You should also separate your application entry point (i.e. your `Application` subclass with its `start(...)` method) from everything else. Have a look at http://stackoverflow.com/questions/32464698/java-how-do-i-start-a-standalone-application-from-the-current-one-when-both-are/32465949#32465949 to see something similar. In that context it is easy to separate the logic from the view in each of the "modules". – James_D Oct 18 '15 at 13:35
  • @Tobi Yes, it has a main method, too. Is it also possible to create a view class containing the rectangles without having a start method? – user3803086 Oct 18 '15 at 16:39
  • that is the problem. One application has only one main method and not more! you can have a view without a main method yes! – Tobi Oct 18 '15 at 16:55

2 Answers2

1

Your problem is that you are creating your own instance of View. When you call the static method main(String[] args), it creates its own instance of View and shows that. Have a look at JavaFX 2.2 Application.

Therefore the instance you called foo isn't the one being shown and so changing properties has no effect. If you read the Javadoc carefully then you could probably do a hack to get the effect that you want but I wouldn't recommend it since you are relying on things that might change in the next release.

If you really want to be able to call Application methods from elsewhere you could do something like this.

In the other class:

private static View view;

public static void setView(View view) {
    this.view = view;
}

Then inside the start method of View, add the line:

OtherClass.setView(this);

On another note, if you are looking for Model/View separation, it might not be a good idea to instantiate the view (application) from within the model (class containing business logic). Doing so is something of a paradox, since the Model is now dependent on the view (i.e. the Model shouldn't know about the rectangle). A better idea would be to instantiate the Model class in the start() method of and have your application work with the interface of your Model. This way your Application class acts as an adapter linking GUI controls to trigger things in your Model.

Devman
  • 310
  • 2
  • 10
  • Thank you very much! My problem is that the bussiness logic changes the view permanently (more precisely the rectangles). Is it in this particular case okay to create a view object in the business logic? – user3803086 Oct 18 '15 at 16:47
  • you can of course create your view everywhere, but you have to remove the second main method! – Tobi Oct 18 '15 at 16:54
  • And how can I display the view when running the class containing the business logic? – user3803086 Oct 18 '15 at 17:05
  • If you call the static method `View.launch(String[] args)` from your other class, it will create an instance of itself an run its own start() method. If you placed your `OtherClass.setView(this)` call inside the start() method, you should get a reference to the View object that is currently being displayed. – Devman Oct 18 '15 at 17:40
  • Also I agree with @Tobi there is no need for a main method in the View class, the only reason to have it in the first place is to call the launch method. – Devman Oct 18 '15 at 17:42
1

You need to remove the main method from your View. In your logic-class you have to save the root Pane you set. And then you can put/change your View into your Pane. Your view cannot extend Application anymore then! Make it extend some Pane.

private final BorderPane rootPane = new BorderPane(); // Class field

// in your start method
final Scene scene = new Scene(rootPane);
primaryStage.setScene(scene);

//Change View like this:
View v = new BView();
rootPane.setCenter(v.getRec());

// later you can set your color
v.setColor()


// Your View class:
public class View{
    private Rectangle rect;

    public View(){
      rect = new Rectangle(10, 10, 100, 100); 
      rect.setFill(Color.WHITE);            
      rect.setStroke(Color.BLACK);
    }

    public Rectangle getRec(){
        return this.rect;
    }
}

Also have a look at this Documentatino here

Tobi
  • 924
  • 1
  • 10
  • 39
  • If I understood correctly, I also have to remove the start method of the View class. Besides, the logic-class has to extend application and implement a start method containing the statements in your post. Unfortunately, the view still doesn´t appear. – user3803086 Oct 18 '15 at 17:46
  • Yes, only one main method in the entire application! And yes those lines. If you want to change your View you can call rootPane.setCenter(xxx) from everywhere else in your main.class – Tobi Oct 18 '15 at 17:48
  • And how can I display the view? I did all like you said, but the window doesn´t appear. – user3803086 Oct 18 '15 at 21:06
  • Please read the documentation!! You need to code primaryStage.show(); – Tobi Oct 18 '15 at 21:58
  • I´m sorry, I were a bit confused. Anyway, now the window appears but without any rectangle. – user3803086 Oct 19 '15 at 12:36
  • You have to adjust your View!! make it a rectangle or call .getRectangle() or something – Tobi Oct 19 '15 at 12:46