Javafx 在对象更改时更新表视图

Javafx updating tableview on object change

我在 java class 中更新 table 视图时遇到一些问题。

package gameStats.controllers;

import gameStats.Main;
import gameStats.model.Team;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.ResourceBundle;

public class MainController implements Initializable {

    private Timeline timeline = new Timeline();
    @FXML
    private Label timerText;
    @FXML
    private Button startTimerButton, stopTimerButton, resetTimerButton, addTeamButton, addPointButton, removePointButton, newTimeButton;
    @FXML
    private TextField teamNameTextfield;
    @FXML
    private TableView teamView;
    @FXML
    private TableColumn<Team, SimpleStringProperty> nameCol;
    @FXML
    private TableColumn<Team, SimpleIntegerProperty> pointCol;

    private ObservableList<Team> obsTeamList;

    private int min;
    private int startTimeSec, startTimeMin;
    private Parent borderPane;
    public BorderPane timeBorderPane;
    private boolean isRunning;

    public void startTimer() {
        if(isRunning == false) {
            if (!(startTimeMin < 0)) {
                KeyFrame keyframe = new KeyFrame(Duration.seconds(1), new EventHandler<ActionEvent>() {
                    @Override
                    public void handle(ActionEvent event) {

                        startTimeSec--;
                        boolean isSecondsZero = startTimeSec == 0;
                        boolean timeToChangeBackground = startTimeSec == 0 && startTimeMin == 0;

                        if (isSecondsZero) {
                            startTimeMin--;
                            startTimeSec = 60;
                        }
                        if (timeToChangeBackground) {
                            timeline.stop();
                            startTimeMin = 0;
                            startTimeSec = 0;
                            timerText.setTextFill(Color.RED);

                        }

                        timerText.setText(String.format("%d min, %02d sec", startTimeMin, startTimeSec));

                    }
                });
                timerText.setTextFill(Color.BLACK);
                startTimeSec = 60; // Change to 60!
                startTimeMin = min - 1;
                timeline.setCycleCount(Timeline.INDEFINITE);
                timeline.getKeyFrames().add(keyframe);
                timeline.playFromStart();
                isRunning = true;
            } else {
                Alert alert = new Alert(Alert.AlertType.INFORMATION, "You have not entered a time!");
                alert.showAndWait();
            }
        }else {
            timeline.play();
        }

    }

    public void setTimer() {
        try {
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(Main.class.getResource("newTimeDialog.fxml"));
            Parent newTimeBorderPane = (BorderPane) loader.load();
            borderPane = newTimeBorderPane;
            Scene scene = new Scene(newTimeBorderPane);
            Stage primaryStage = new Stage();
            primaryStage.setScene(scene);
            primaryStage.showAndWait();
            if (!primaryStage.isShowing()) {
                min = NewTimeController.getMin();
                timerText.setText(min + "min, " + 00 + "sec");
            } else {

            }

        } catch (IOException e) {
            e.printStackTrace();
        }


    }

    public void stopTimer() {

        timeline.pause();
    }

    public void resetTimer() {
        timeline.stop();
        startTimeSec = 60;
        startTimeMin = min-1;
        timerText.setText(String.format("%d min, %02d sec", startTimeMin, startTimeSec));
    }

    public void createTeam(){

        SimpleStringProperty name = new SimpleStringProperty(teamNameTextfield.getText());
        SimpleIntegerProperty startPoint = new SimpleIntegerProperty(0);
        if(!(obsTeamList.size() == 0)){
            for (Team t : obsTeamList) {
                if (!t.getName().equals(name)) {
                    obsTeamList.add(new Team(name, startPoint));
                    teamView.getItems().setAll(obsTeamList);
                }else {
                    Alert alert = new Alert(Alert.AlertType.INFORMATION, "Holdet eksistere allerede!");
                    alert.showAndWait();
                }
            }
        }else{
            obsTeamList.add(new Team(name, startPoint));
            teamView.getItems().setAll(obsTeamList);
        }

    }

    public void addPoint(){
        Team teamToAddPointsTo = (Team) teamView.getSelectionModel().getSelectedItem();
        teamToAddPointsTo.setPoints(new SimpleIntegerProperty(1));
    }
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        obsTeamList = FXCollections.observableArrayList(new ArrayList<>());
        nameCol.setCellValueFactory(new PropertyValueFactory<>("name"));
        pointCol.setCellValueFactory(new PropertyValueFactory<>("points"));


    }
}

型号class:

package gameStats.model;

import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

/**
 * Created by lassebjorklund on 21/01/16.
 * For JuniorEvent_kampdata
 */
public class Team {

    private SimpleStringProperty name;
    private SimpleIntegerProperty points;

    public Team(SimpleStringProperty name, SimpleIntegerProperty points) {
        this.name = name;
        this.points = points;
    }

    public String getName() {
        return name.get();
    }

    public SimpleStringProperty nameProperty() {
        return this.name;
    }

    public int getPoints() {
        return points.get();
    }

    public SimpleIntegerProperty pointsProperty() {
        return this.points;
    }

    public void setName(String name) {
        this.name.set(name);
    }

    public void setPoints(SimpleIntegerProperty points) {
        this.points.add(points);
    }

    @Override
    public String toString() {
        return getName() + " : " + getPoints();
    }
}

我希望能够在 table 视图中更新所选团队的分数。我希望在按下调用 "addPoint" 方法的按钮时发生这种情况。但我不知道该怎么做。

您的代码有多个问题。

  1. 列的类型应该是基础数据类型,而不是 属性 类型。对于 SimpleStringProperty 使用 TableColumn<Team, String>。对于 SimpleIntegerProperty 使用 TableColumn<Team, Integer>TableColumn<Team, Number>
  2. setPoints 方法应该采用 intInteger,而不是 SimpleIntegerProperty。它应该与 getPoints returns 的类型相同。
  3. setPoints中,你应该使用points.setpoints.add 创建一个新的 NumberExpression 来表示两个属性的相加,但不会更改实际的 属性。

同样,将 Team 的实际属性作为最终字段,并且只更改它们的值可能是个好主意。有关详细信息,请参阅 this tutorial