【问题标题】:TableView is not populating when taking input from user, but populates when new Object is added explicitlyTableView 在接受用户输入时不填充,但在显式添加新对象时填充
【发布时间】:2018-06-13 04:45:50
【问题描述】:

这是我第一次使用 JavaFX 和 TableView。我有一个应用程序,用户可以输入高尔夫分数来为他们生成让分值。

我有一个 ArrayList 用作我的“数据库”:

public ArrayList<Score> scoreDB = new ArrayList<>();

用这个作为加值的方法:

public static Score scoreSubmit(DatePicker roundDate, TextField courseName, TextField courseRating, TextField courseSlope, TextField score)
{
    Score temp = new Score();
    //Wanted to use own Date class, must use this roundabout way to set the date correctly
    LocalDate tempDate = roundDate.getValue();

    temp.setRoundDate(tempDate.getMonthValue(), tempDate.getDayOfMonth(), tempDate.getYear());
    temp.setCourseName(courseName.getText());
    temp.setCourseRating(Double.valueOf(courseRating.getText()));
    temp.setCourseSlope(Double.valueOf(courseSlope.getText()));
    temp.setScore(Double.valueOf(score.getText()));

    return temp;
}

注意:我使用了我自己创建的日期类。

我检查了该方法是否确实有效,并且 ArrayList 确实收到了一个值。

这是我构建的 TableView:

//Table columns
    //Creating columns and setting the display to call the values from Score class
    TableColumn<Score, String> courseNameColumn = new TableColumn<>("Course Name");
    courseNameColumn.setMinWidth(100);
    courseNameColumn.setCellValueFactory(new PropertyValueFactory<>("courseName"));

    TableColumn<Score, Date> dateColumn = new TableColumn<>("Date");
    dateColumn.setMinWidth(100);
    dateColumn.setCellValueFactory(new PropertyValueFactory<>("roundDate"));

    TableColumn<Score, Double> scoreColumn = new TableColumn<>("Score");
    scoreColumn.setMinWidth(100);
    scoreColumn.setCellValueFactory(new PropertyValueFactory<>("score"));

    //This adds rating and slope under one column
    TableColumn courseDataColumn = new TableColumn("Course Data");
    TableColumn<Score, Double> courseRatingColumn = new TableColumn<>("Course Rating");
    TableColumn<Score, Double> courseSlopeColumn = new TableColumn<>("Course Slope");
    courseDataColumn.getColumns().addAll(courseRatingColumn, courseSlopeColumn);
    courseDataColumn.setMinWidth(100);
    courseRatingColumn.setCellValueFactory(new PropertyValueFactory<>("courseRating"));
    courseSlopeColumn.setCellValueFactory(new PropertyValueFactory<>("courseSlope"));

    scoreTable.getColumns().addAll(courseNameColumn, dateColumn, scoreColumn, courseDataColumn);

    displayLayout.setCenter(displaySP);
    displaySP.setBackground(new Background(new BackgroundFill(Paint.valueOf("#006400"), CornerRadii.EMPTY, Insets.EMPTY)));
    displaySP.getChildren().add(scoreTable);
    displayLayout.setBottom(displayHbox);

    scoreTable.setItems(addScore());

以下是我的分数课程中的变量:

private double score = 0.0;
private double courseRating = 0.0;
private double courseSlope = 0.0;
private String courseName = "";
private Date roundDate;

这是我的分数类吸气剂(我已经读过这些必须以某种方式命名才能工作):

public double getScore()
{
    return score;
}
public String getCourseName()
{
    return courseName;
}
public Double getCourseSlope()
{
    return courseSlope;
}
public double getCourseRating()
{
    return courseRating;
}
public Date getRoundDate()
{
    return roundDate;
}

这里是返回可观察列表的方法:

public ObservableList<Score> addScore()
{
    ObservableList<Score> scores = FXCollections.observableArrayList();

   // scores.add(new Score());

    for (int i = 0; i < scoreDB.size(); i++)
    {
        scores.add(scoreDB.get(i));
    }

    return scores;
}

当仅使用注释掉的 new Score() 时,表格会填充此默认分数。使用 for 循环时,不会填充任何内容。

非常感谢任何帮助。

【问题讨论】:

  • 代码中存在结构问题,但我猜你也有逻辑错误。在 scoreDB 中提交对象时不清楚,因为在上面的代码中,数组将为空且符合逻辑,循环不会执行任何操作。
  • scoreSubmit 似乎没有将Score 对象添加到任何数据结构中。它不是从您发布的任何代码 sn-p 调用的,您也没有描述它是如何调用的。是否调用了此方法?是使用结果还是按照方法名称建议的方式使用方法(即您假设该方法修改了某些数据结构)?
  • 请阅读stackoverflow.com/help/mcve并采取相应措施。

标签: java javafx arraylist tableview observablelist


【解决方案1】:

对于初学者,您应该注意您的模型(Score 类)。与Properties 一起工作很好(但不一定)。这样做的原因是您将能够编辑值并且更改将自动反映在视图中(TableView)。否则,如果您对已添加的数据进行任何更改,则需要手动更新它,因为PropertyValueFactory 将生成只读属性。

public class Score {
    private DoubleProperty score = new SimpleDoubleProperty(0.0);
    private DoubleProperty courseRating = new SimpleDoubleProperty(0.0);
    private DoubleProperty courseSlope = new SimpleDoubleProperty(0.0);
    private StringProperty courseName = new SimpleStringProperty("");
    private ObjectProperty<LocalDate> roundDate = new SimpleObjectProperty<>();

    public double getScore() {
        return score.get();
    }

    public DoubleProperty scoreProperty() {
        return score;
    }

    public void setScore(double score) {
        this.score.set(score);
    }

    public double getCourseRating() {
        return courseRating.get();
    }

    public DoubleProperty courseRatingProperty() {
        return courseRating;
    }

    public void setCourseRating(double courseRating) {
        this.courseRating.set(courseRating);
    }

    public double getCourseSlope() {
        return courseSlope.get();
    }

    public DoubleProperty courseSlopeProperty() {
        return courseSlope;
    }

    public void setCourseSlope(double courseSlope) {
        this.courseSlope.set(courseSlope);
    }

    public String getCourseName() {
        return courseName.get();
    }

    public StringProperty courseNameProperty() {
        return courseName;
    }

    public void setCourseName(String courseName) {
        this.courseName.set(courseName);
    }

    public LocalDate getRoundDate() {
        return roundDate.get();
    }

    public ObjectProperty<LocalDate> roundDateProperty() {
        return roundDate;
    }

    public void setRoundDate(LocalDate roundDate) {
        this.roundDate.set(roundDate);
    }
}

您还必须更改“数据库”。您必须使用Observable 集合而不是普通的List。这将允许您直接向其中添加数据,它们将自动出现在表格中

public ObservableList<Score> scoreDB = FXCollections.observableArrayList();
...

//scoreTable.setItems(addScore());
scoreTable.setItems(scoreDB);

...

public void scoreSubmit() {
    Score temp = new Score();

    temp.setRoundDate(roundDate.getValue());
    temp.setCourseName(courseName.getText());
    temp.setCourseRating(Double.valueOf(courseRating.getText()));
    temp.setCourseSlope(Double.valueOf(courseSlope.getText()));
    temp.setScore(Double.valueOf(score.getText()));

    scoreDB.add(temp);
}

更新

这是一个工作示例,几乎使用了您展示的整个结构。由于Double#valueOf 电话,数据输入不堪重负,您可能会收到NumberFormatException。为了避免这个问题,最好使用TextFormatter

public class Main extends Application {

    private DatePicker roundDate = new DatePicker();
    private TextField courseName = new TextField();
    private TextField courseRating = new TextField();
    private TextField courseSlope = new TextField();
    private TextField score = new TextField();
    private TableView<Score> scoreTable = new TableView<>();

    public ObservableList<Score> scoreDB = FXCollections.observableArrayList();

    @Override
    public void start(Stage primaryStage) throws Exception{

        //Table columns
        //Creating columns and setting the display to call the values from Score class
        TableColumn<Score, String> courseNameColumn = new TableColumn<>("Course Name");
        courseNameColumn.setMinWidth(100);
        courseNameColumn.setCellValueFactory(new PropertyValueFactory<>("courseName"));

        TableColumn<Score, LocalDate> dateColumn = new TableColumn<>("Date");
        dateColumn.setMinWidth(100);
        dateColumn.setCellValueFactory(new PropertyValueFactory<>("roundDate"));

        TableColumn<Score, Double> scoreColumn = new TableColumn<>("Score");
        scoreColumn.setMinWidth(100);
        scoreColumn.setCellValueFactory(new PropertyValueFactory<>("score"));

        //This adds rating and slope under one column
        TableColumn courseDataColumn = new TableColumn("Course Data");
        TableColumn<Score, Double> courseRatingColumn = new TableColumn<>("Course Rating");
        TableColumn<Score, Double> courseSlopeColumn = new TableColumn<>("Course Slope");
        courseDataColumn.getColumns().addAll(courseRatingColumn, courseSlopeColumn);
        courseDataColumn.setMinWidth(100);
        courseRatingColumn.setCellValueFactory(new PropertyValueFactory<>("courseRating"));
        courseSlopeColumn.setCellValueFactory(new PropertyValueFactory<>("courseSlope"));

        scoreTable.getColumns().addAll(courseNameColumn, dateColumn, scoreColumn, courseDataColumn);
        scoreTable.setItems(scoreDB);

        Button addButton = new Button("Add");
        addButton.setOnAction(e -> scoreSubmit());

        HBox displayHbox = new HBox();
        displayHbox.setSpacing(5);
        displayHbox.getChildren().addAll(roundDate, courseName, courseRating, courseSlope, score, addButton);

        BorderPane displayLayout = new BorderPane();
        displayLayout.setCenter(scoreTable);
        displayLayout.setBottom(displayHbox);

        primaryStage.setScene(new Scene(displayLayout));
        primaryStage.show();
    }

    public void scoreSubmit() {
        Score temp = new Score();

        temp.setRoundDate(roundDate.getValue());
        temp.setCourseName(courseName.getText());
        temp.setCourseRating(Double.valueOf(courseRating.getText()));
        temp.setCourseSlope(Double.valueOf(courseSlope.getText()));
        temp.setScore(Double.valueOf(score.getText()));

        scoreDB.add(temp);
    }

    public static void main(String[] args) {
        launch(args);
    }
}

【讨论】:

  • 我已经创建了一个新的 ScoreProperty 类,现在正在为我的表使用该类。仍然没有运气,我从用户那里获得输入的唯一方法是还专门创建一个 score 对象。
  • @DrSooch 你做错了什么,但是因为你没有显示代码,所以不能说到底是什么。看看我上面帖子的食谱。我添加了一个粗略(但有效)的示例,将数据添加到表中。
【解决方案2】:

我不确定我做了什么,但我似乎已经修复了它。这是我的 scoreSubmit() 方法实现:

 //Submit Button for score scene, implements method for setting Score Class variables
    Button scoreSubmit = GHINAppMethods.submitButton();
    scoreSubmit.defaultButtonProperty().bind(nameInput.focusedProperty());
    scoreSubmit.setOnAction(e ->
    {
        //checks to make sure values are correct
        switch (GHINAppMethods.checkScoreValues(courseRating, courseSlope, score))
        {
            //all values valid
            case 0:
            {
                //adds score to a "database" that will eventually be used in ScoreHistory class
                scoreDB.add(GHINAppMethods.scoreSubmit(roundDateTest, courseName, courseRating, courseSlope, score));
               //ScoreIterator has no use at this point
                System.out.println(scoreDB.get(scoreIterator));
                scoreIterator++;
                System.out.println(scoreIterator);
                System.out.println(scoreDB.size());
                GHINAppMethods.addAnotherScore(scoreTextFields, clearAll, displayScene, entryWindow, scoreTable, scores);
                break;
            }
            //rating invalid
            case 1:
            {
                courseRating.clear();
                GHINAppMethods.ratingInvalid();
                break;
            }
            //slope invalid
            case 2:
            {
                courseSlope.clear();
                GHINAppMethods.slopeInvalid();
                break;
            }
            //score invalid
            case 3:
            {
                score.clear();
                GHINAppMethods.scoreInvalid();
                break;
            }
            //Fatal System Error (shouldn't be used)
            default:
            {
                GHINAppMethods.fatalError();
                System.out.println("fatal error");
                System.exit(0);
                break;
            }
        }
    });

checkScoreValues() 方法只是检查以确保值正确(我仍然错过了异常,但它有帮助)。 checkScoreValues 返回一个 int,switch 语句将执行。 scoreDB.add(...) 和 addAnotherScore() 是唯一实际使用的方法。其他的用于错误检查。

【讨论】:

    猜你喜欢
    • 2017-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-31
    相关资源
    最近更新 更多