Komunikacja między kontrolerami, JavaFX

0

Hej, ostatnio zacząłem robić projekt w JavaFX, gdzie muszę zaimplementować listę todo. Jednakże nie wiem jak mógłbym przesyłać dane między oknami. Ogólnie mam główne okno, po czym wciskając przycisk add new task wyskakuje nowe okno, gdzie uzupełniam dane zadania i chciałbym zatwierdzając ten obiekt(klasa przetrzymująca same dane typu tytuł, priorytet itp.) chciałbym wysłać go do pierwszego okna, gdzie pojawiłby się na ListView. Mój kod obecnie wygląda tak:
Główny kontroler"

public class Controller {
    TaskDescription tmp;

    @FXML
    private ListView<TaskDescription> toDo;

    @FXML
    private ListView<TaskDescription> inProgress;

    @FXML
    private ListView<TaskDescription> doneTasks;

    @FXML
    private Button addTask;

    ObservableList<TaskDescription> list = FXCollections.observableArrayList();

    @FXML
    void addNewTask(ActionEvent event) throws Exception {

        FXMLLoader loader = new FXMLLoader(getClass().getResource("NewTask.fxml"));
        Parent root= (Parent) loader.load();

        Stage stage = new Stage();
        stage.setScene(new Scene(root, 600, 500));
        stage.showAndWait();
        NewTaskController getControl=loader.getController();

        toDo.setItems(list);
    }

a drugi:

public class NewTaskController {


    TaskDescription tmp;

    @FXML
    private TextField taskTitle;

    @FXML
    private ComboBox<String> choosePriority;

    @FXML
    private String lowTask;

    @FXML
    private String highTask;

    @FXML
    private DatePicker chooseDate;

    @FXML
    private TextArea textArea;

    @FXML
    private Button addTaskButton;

    @FXML
    void addTask(ActionEvent event) {
    tmp.title=taskTitle.getText();
    tmp.priority=choosePriority.getValue();
    tmp.date=chooseDate.getValue();
    tmp.description=textArea.getText();

    addTaskButton.getScene().getWindow().hide();
    }

}
1

Użyj do komunikacji między kontrolerami, EventBusa z Guavy.

0

Niestety nie byłem w stanie ogarnąć Event Busa, więc zrobiłem to innym sposobem, a mianowicie w drugim kontrolerze przycisk uruchamia funkcję pierwszego kontrolera, która przyjmuje ustawiony element, ale żeby ją uruchomić, musi być ona statyczna. Ale wtedy znów moja ObservableList i ListView muszą być statyczne. I tu się pojawia problem, że(prawdopodobnie o to chodzi) jak ListView jest statyczne, to owszem, dodaje do niego elementy(sprawdzałem w debuggerze), jednak w oknie aplikacji w ListView nie pojawiają się te obiekty.

public class Controller {

    @FXML
    private static  ListView<TaskDescription> toDo=new ListView<>();

    @FXML
    private ListView<TaskDescription> inProgress;

    @FXML
    private ListView<TaskDescription> doneTasks;

    @FXML
    private Button addTask;

    static ObservableList<TaskDescription> list= FXCollections.observableArrayList();

    @FXML
    void addNewTask(ActionEvent event) throws Exception {

        FXMLLoader loader = new FXMLLoader(getClass().getResource("NewTask.fxml"));
        Parent root= (Parent) loader.load();
        Stage stage = new Stage();
        stage.setScene(new Scene(root, 600, 500));
        stage.show();
    }
    static void addToList(TaskDescription tmp)
    {

        TaskDescription newTask=new TaskDescription(tmp);
        list.add(newTask);
        toDo.setItems(list);
        
        System.out.println(list);
    }
}

Funkcja w drugim kontrolerze:

    @FXML
    void addTask(ActionEvent event) {

        tmp=new TaskDescription(taskTitle.getText(),choosePriority.getValue(),chooseDate.getValue(),textArea.getText());
        System.out.println(tmp);
        Controller.addToList(tmp);
    }

1

No więc tak, tutaj jest moja wersja z zaimplementowanym EventBusem: https://github.com/matadini/todo-list-4programmers-help
Pozwolisz że będę miał dla Ciebie kilka uwag / porad, jak je już znasz to super a jak nie to może się czegoś dowiesz.

  1. Do budowania projektów używaj jakiegoś Maven'a albo Gradle'a. Nie uzależniasz projektu od IDE i co więcej, taki maven wymusza na Tobie określoną strukturę katalogów więc wiesz gdzie co wrzucać.
  2. Jak będziesz się bawił FX'em to polecałbym aby informację o kontrolerze i powiązanych metodach z kontrolkami, umieszczać w kontrolerze a sam kontroler ustawiać jawnie. Deklarować powiązania jawnie w void initialize() Z mojego doświadczenia wynika (2 lata w JFX :D) że te magiczne mechanizmy sprawiają problemy gdy chce się zrobić coś ambitniejszego np. tak jak u Ciebie, zarejestrować kontroler na EventBusie.
  3. EventBus tylko z Guavy, ten od GreenRobota ma brzydki błąd w obsłudze subskrybentów będących klasami package-scope-private. Guava zawsze na propsie. ;)
  4. Jak masz zestaw: kontroler + fxml, zachowuj konwencję, najlepiej: MainPane.fxml + MainPaneController.java. Nazwy Controller.java + sample.fxml absolutnie nic nie mówią.
  5. Zmienne powinny mieć zakres "maksymalnie wymagany" ta tmp w Controller.java powinna być lokalna aby niepotrzebnie nie zwiększać jej widoczności.

Słowem podsumowania wyrażę dość niepopularną opinię, mianowicie: JavaFX to spoko technologia, warto się nią pobawić, potrzeba w niej trochę wprawy ale pozwala ona nauczyć się wzorca MVC na żywych przykładach.

1 użytkowników online, w tym zalogowanych: 0, gości: 1