繁体   English   中英

如何通过 window 2 和 JavaFX 中的按钮操作更新 window 1 中的 TableView

[英]How do I update a TableView in window 1 by an action of a button in window 2 with JavaFX

从昨天开始,我一直在搜索和思考这个问题。 现在大约10个小时。 我已经浏览了所有与我的问题有任何相似之处的现有线程,但没有一个对我有帮助。 我尝试过使用所谓的“回调”方法,但我仍然无法让它工作。

情况:

  • 我在一个 window 的选项卡中有一个 TableView。
  • 在持有该 TableView 的场景中有一个按钮
  • 该按钮打开一个新的 window(显示了一个新阶段)
  • 在那个新阶段,用户可以在第一个 window 中为 TableView 添加一个新条目。

我如何做到这一点,以便在创建 TableView 的新条目后,该条目立即显示在 tableview 中。 如何在从第二个窗口(阶段)为其创建新条目时刷新 TableView? 基本上,我需要实现的是让一个 controller 由另一个不在同一个 window 中的 controller 触发的方法。

这是 TableView 所在的第一阶段(“lectureHallsTableView”)的 controller。

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();

    }

}

这是第二个 window 的 controller ,通过它可以创建一个新条目:

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();
            }
        });
    }
}

我已经实现了这个答案所详述的内容。 我所做的要点是,我创建了一个新的 class,其目的是“托管” ObservableList,然后我的两个窗口/阶段从中读取它们的数据。 由于可观察列表会自动通知我的 tableView 任何更改,通过在一个窗口/阶段对其进行更改(例如在我的情况下添加新条目),另一个 window 自动并立即显示更改在它的 tableView 中。

这是我创建的 class 这是我需要的

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();
    }

}

这是 window 的 controller 产生第二个 window

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());
    }

}

这是第二个窗口的 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;
    }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM