0

I spent a lot of time with this problem trying different solutions without success. I want to sent a count value (Buttons clicks) from class ViewPart2 to class ViewPart1. In ViewPart1, I want to update label text.

public class Test extends Application {

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

    @Override
    public void start(Stage stage) throws Exception {

        BorderPane root = new BorderPane();
        Scene scene = new Scene(root, 300, 200);
        stage.setScene(scene);
        stage.show();

        new ViewPart1().createGui(root);
        new ViewPart2().createGui(root);
    }

}

public class ViewPart2 {
    private int count = 0;

    public void createGui(BorderPane root) {
        Button btn = new Button("Click me!");
        root.setLeft(btn);

        btn.setOnAction(event -> {
            count++;
            new ViewPart1().setCount(count);
            // how can I send count value to ViewPart1 and update label text
        });

    }
}

public class ViewPart1 {
    private int count;

    public void createGui(BorderPane root) {

        Label lbl = new Label("-");
        root.setCenter(lbl);
        lbl.setText(count + "Clicks");

    }

    public void setCount(int count) {

        this.count = count;

    }

}
altocumulus
  • 21,179
  • 13
  • 61
  • 84
Sam Joos
  • 430
  • 2
  • 11
  • 25
  • Something is missing in your first code fragment. There are 3 '}' but only 2 '{'. Please edit this question. I suggest also deleting some of emptylines in your code. Then post will be more concise. – rtruszk Nov 21 '14 at 22:09
  • You're right. I posted the wrong class I changed it, sorry for this mistake. – Sam Joos Nov 22 '14 at 09:00

1 Answers1

0

This solution is perhaps slightly overkill, but you can create a model class, pass it as input to both of your view classes. And the views can modify the model and observe changes on it.

enter image description here

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.*;
import javafx.geometry.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;

public class Clicker extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        final ClickCounter clickCounter = new ClickCounter();

        final ClickInputView  inputView  = new ClickInputView(clickCounter);
        final ClickOutputView outputView = new ClickOutputView(clickCounter);

        VBox layout = new VBox(10,
                inputView,
                outputView
        );
        layout.setPadding(new Insets(10));
        layout.setAlignment(Pos.CENTER);

        stage.setScene(new Scene(layout));
        stage.show();
    }

    private class ClickCounter {
        private final ReadOnlyIntegerWrapper numClicks =
                new ReadOnlyIntegerWrapper(0);

        public int getNumClicks() {
            return numClicks.get();
        }

        public ReadOnlyIntegerProperty numClicksProperty() {
            return numClicks.getReadOnlyProperty();
        }

        public void click() {
            numClicks.set(getNumClicks() + 1);
        }
    }

    private class ClickInputView extends StackPane {
        private final Button button = new Button("Click Me!");

        public ClickInputView(ClickCounter clickCounter) {
            button.setOnAction(event -> clickCounter.click());

            getChildren().setAll(button);
        }
    }

    private class ClickOutputView extends StackPane {
        private final Label clickCountLabel = new Label();

        public ClickOutputView(ClickCounter clickCounter) {
            clickCountLabel.textProperty().bind(
                    Bindings.format(
                            "Clicked %d times",
                            clickCounter.numClicksProperty()
                    )
            );
            clickCountLabel.setMinWidth(150);
            clickCountLabel.setAlignment(Pos.CENTER);

            getChildren().setAll(clickCountLabel);
        }
    }

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

Because the model is shared between the classes it allows a way for the views to reflect changes to a common data structure without needing to be aware of the existence of each other. It also means that model code is segregated from your view code and can be tested separately.

For a more complete solution you can look at a dependency injection based framework such as afterburner.fx that also makes use of FXML for your views moving the view definition out of Java into XML and the style definition into CSS.

jewelsea
  • 150,031
  • 14
  • 366
  • 406