Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
236 views
in Technique[技术] by (71.8m points)

java - How do I update a TableView in window 1 by an action of a button in window 2 with JavaFX

I've been seraching and thinking about this since yesterday. Some 10 hours now. I've gone through all of the existing threads which hold any similarity to my question, none of it has helped me. I've tried to do with the so called "Callback" method, but I can't get it to work even still.

The situation:

  • I have a TableView in a tab of one window.
  • In the scene holding that TableView there is a button
  • The button opens a new window (a new stage is shown)
  • In that new stage the user can add a new entry for the TableView in the first window.

How do I make it so that after a new entry for the TableView is created, that entry is immediately shown in the tableview. How do I make that TableView refresh upon a new entry being created for it from that 2nd window(stage)? Basically, what I need to achieve is to have a method of one controller be triggered by another controller which isn't in the same window.

This is the controller of the first stage in which the TableView is (the "lectureHallsTableView").

package main.JavaFX;

import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Modality;
import javafx.stage.Stage;
import main.classes.LectureHall;
import main.sqlite.DatabaseCommunicaton;

import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;

public class LectureHallsTabController {
    @FXML
    private TableView<LectureHall> lectureHallsTableView;
    @FXML
    private Button addNewLectureHallButton;
    @FXML
    private Button deleteLectureHallButton;

    private TableColumn<LectureHall, String> column1;
    private TableColumn<LectureHall, Integer> column2;

    ArrayList<LectureHall> lhlist = new ArrayList<>();
    DatabaseCommunicaton dbcomm = new DatabaseCommunicaton();

    public void initialize() throws SQLException {
        column1 = new TableColumn<>("Hall code");
        column2 = new TableColumn<>("Hall capacity");
        column1.setCellValueFactory(new PropertyValueFactory<>("hallCode"));
        column2.setCellValueFactory(new PropertyValueFactory<>("capacity"));
        lectureHallsTableView.getColumns().add(0, column1);
        lectureHallsTableView.getColumns().add(1, column2);
        lhlist = dbcomm.queryLectureHalls();
        lectureHallsTableView.getItems().addAll(lhlist);

        /**
         * Delete button functionality
         */
        deleteLectureHallButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent actionEvent) {
                LectureHall selectedItem = lectureHallsTableView.getSelectionModel().getSelectedItem();
                try {
                    lhlist = dbcomm.deleteLectureHall(selectedItem.getId());
                    lectureHallsTableView.getItems().clear();
                    lectureHallsTableView.getItems().addAll(lhlist);
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        });

    }
    /**
     * populates the tableView with all the existing database entries
     */
    public void refreshLectureHalls() throws SQLException {
        lhlist = dbcomm.queryLectureHalls();
    }

    public void openLectureHallInputWindow(ActionEvent actionEvent) {
        Stage stage = new Stage();
        Parent root = null;
        try {
            root = FXMLLoader.load(getClass().getResource("lectureHallInput.fxml"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        stage.setTitle("Lecture Input");
        stage.setScene(new Scene(root));
        stage.setResizable(false);

        // Serves the purpose of the new window being imposed over the other window
        stage.initModality(Modality.APPLICATION_MODAL);

        stage.show();

    }

}

This is the controller of the 2nd window through which one can create a new entry:

package main.JavaFX;

import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
import main.sqlite.DatabaseCommunicaton;

import java.sql.SQLException;

public class LectureHallInputController {

    @FXML
    private Button confirmButton;
    @FXML
    private Button cancelButton;
    @FXML
    private TextField hallCodeField;
    @FXML
    private TextField hallCapacityField;

    public void initialize() {

        cancelButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent actionEvent) {
                Stage stage = (Stage) cancelButton.getScene().getWindow();
                stage.close();
            }
        });
   
        confirmButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent actionEvent) {
                String hallCode = hallCodeField.getText();
                int hallCapacity = Integer.parseInt(hallCapacityField.getText());
                DatabaseCommunicaton dbcomm = new DatabaseCommunicaton();
                try {
                    dbcomm.addLectureHall(hallCode, hallCapacity);
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                Stage stage = (Stage) confirmButton.getScene().getWindow();
                stage.close();
            }
        });
    }
}
question from:https://stackoverflow.com/questions/65849548/how-do-i-update-a-tableview-in-window-1-by-an-action-of-a-button-in-window-2-wit

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I have implemented what this answer detailed on. The gist of what I've done is that I've created a new class which serves the purpose of "hosting" the ObservableList from which my two windows/stages then read their data. As the observable list automatically notifies my tableView of any changes to it, by introducing a change to it (such as what in my case is adding a new entry) with one window/stage, the other window automatically and right away has the change displayed in its tableView.

This is the class that I've created which is what I needed

public class LectureHallData{
    DatabaseCommunicaton dbcomm = new DatabaseCommunicaton();

    public ObservableList<LectureHall> getLectureHallList() {
        return lectureHallList;
    }

    public ObservableList<LectureHall> lectureHallList = FXCollections.observableArrayList(lectureHall -> new Observable[]{lectureHall.codeProperty(), lectureHall.capacityProperty()});
    private ObjectProperty<LectureHall> currentLectureHall = new SimpleObjectProperty<>();

    public ObservableList<LectureHall> loadLectureHalls() throws SQLException {
        ObservableList<LectureHall> lectureHallObservableList = FXCollections.observableArrayList(dbcomm.queryLectureHalls());
        this.lectureHallList = lectureHallObservableList;
        return lectureHallObservableList;
    }

    public void refreshLectureHalls() throws SQLException {
        this.lectureHallList.clear();
        this.lectureHallList.addAll(FXCollections.observableArrayList(dbcomm.queryLectureHalls()));
    }

    public void addLectureHall(String hallCode, int hallCapacity) throws SQLException {
        dbcomm.addLectureHall(hallCode, hallCapacity);
        refreshLectureHalls();
    }

}

This is the controller of the window from which the 2nd window is spawned

public class LectureHallsTabController {
    @FXML
    private TableView<LectureHall> lectureHallsTableView;
    @FXML
    private Button addNewLectureHallButton;
    @FXML
    private Button deleteLectureHallButton;

    private TableColumn<LectureHall, String> column1;
    private TableColumn<LectureHall, Integer> column2;

    ArrayList<LectureHall> lhlist = new ArrayList<>();
    DatabaseCommunicaton dbcomm = new DatabaseCommunicaton();
    private LectureHallData data;

    public void initialize() throws SQLException {

        initData();


    }

  public void openLectureHallInputWindow(ActionEvent actionEvent) {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("lectureHallInput.fxml"));
        Stage stage = new Stage();
        Parent root = null;
        try {
            root = loader.load();
        } catch (IOException e) {
            e.printStackTrace();
        }

        LectureHallInputController lectureHallInputController = loader.getController();
        lectureHallInputController.initData(data);
        stage.setTitle("Lecture Input");
        stage.setScene(new Scene(root));
        stage.setResizable(false);

        // Serves the purpose of the new window being imposed over the other window
        stage.initModality(Modality.APPLICATION_MODAL);

        stage.show();

    }

    public void initData() throws SQLException {
        // ensure data is only set once:
        if (this.data != null) {
            throw new IllegalStateException("Data can only be initialized once");
        }
        this.data=new LectureHallData();
        column1 = new TableColumn<>("Hall code");
        column2 = new TableColumn<>("Hall capacity");
        column1.setCellValueFactory(new PropertyValueFactory<>("hallCode"));
        column2.setCellValueFactory(new PropertyValueFactory<>("capacity"));
        lectureHallsTableView.getColumns().add(0, column1);
        lectureHallsTableView.getColumns().add(1, column2);

        lectureHallsTableView.getItems().clear();
        data.loadLectureHalls();
        lectureHallsTableView.setItems(data.getLectureHallList());
    }

}

This is the 2nd window's controller

public class LectureHallInputController {

    @FXML
    private Button confirmButton;
  
   ...

    private LectureHallData data;

    public void initialize() {

    ...

    confirmButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent actionEvent) {
                String hallCode = hallCodeField.getText();
                int hallCapacity = Integer.parseInt(hallCapacityField.getText());
                try {
                    data.addLectureHall(hallCode, hallCapacity);
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
                Stage stage = (Stage) confirmButton.getScene().getWindow();
                stage.close();
            }
        });
    }

    public void initData(LectureHallData data) {
        this.data = data;
    }

}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...