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" 方法的按钮时发生这种情况。但我不知道该怎么做。
您的代码有多个问题。
- 列的类型应该是基础数据类型,而不是 属性 类型。对于
SimpleStringProperty
使用 TableColumn<Team, String>
。对于 SimpleIntegerProperty
使用 TableColumn<Team, Integer>
或 TableColumn<Team, Number>
。
setPoints
方法应该采用 int
或 Integer
,而不是 SimpleIntegerProperty
。它应该与 getPoints
returns 的类型相同。
- 在
setPoints
中,你应该使用points.set
。 points.add
创建一个新的 NumberExpression
来表示两个属性的相加,但不会更改实际的 属性。
同样,将 Team
的实际属性作为最终字段,并且只更改它们的值可能是个好主意。有关详细信息,请参阅 this tutorial。
我在 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" 方法的按钮时发生这种情况。但我不知道该怎么做。
您的代码有多个问题。
- 列的类型应该是基础数据类型,而不是 属性 类型。对于
SimpleStringProperty
使用TableColumn<Team, String>
。对于SimpleIntegerProperty
使用TableColumn<Team, Integer>
或TableColumn<Team, Number>
。 setPoints
方法应该采用int
或Integer
,而不是SimpleIntegerProperty
。它应该与getPoints
returns 的类型相同。- 在
setPoints
中,你应该使用points.set
。points.add
创建一个新的NumberExpression
来表示两个属性的相加,但不会更改实际的 属性。
同样,将 Team
的实际属性作为最终字段,并且只更改它们的值可能是个好主意。有关详细信息,请参阅 this tutorial。