【问题标题】:How do I update a TableView in window 1 by an action of a button in window 2 with JavaFX如何使用 JavaFX 通过窗口 2 中的按钮操作来更新窗口 1 中的 TableView
【发布时间】:2021-01-23 04:42:10
【问题描述】:

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

情况:

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

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

这是 TableView 所在的第一阶段的控制器(“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();

    }

}

这是第二个窗口的控制器,通过它可以创建一个新条目:

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

【问题讨论】:

  • 这是一个ListView 示例,但我认为这些想法应该是相同的。 stackoverflow.com/questions/55668795/…
  • 我已经用您的链接答案作为指导工作了 3 个小时,唉,我已经成功了。我已经实现了“中介”类,其目的是“托管” ObservableList,然后我的两个不同的窗口(阶段)从中接收它们的数据。另外:“你(我)已经撤消了你对这条评论的投票;你(我)不能再投票了。” - 很抱歉。

标签: java javafx


【解决方案1】:

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

这是我创建的我需要的类

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

}

这是生成第二个窗口的窗口的控制器

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

}

这是第二个窗口的控制器

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

}

【讨论】:

    猜你喜欢
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多