Can't populate JavaFX TableView created in SceneBuilder 2

谁说胖子不能爱 提交于 2020-06-10 06:43:06

问题


I am trying to re-create the table view sample using scene builder 2, but my TableView couldn’t be populated.

I defined my table in JavaFx SceneBuilder like so:

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane id="AnchorPane" prefHeight="380.0" prefWidth="462.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="tableviewsample.FXMLDocumentController">
    <children>
        <Button fx:id="button" layoutX="325.0" layoutY="324.0" onAction="#handleButtonAction" text="Click Me!" />
        <Label fx:id="label" layoutX="126" layoutY="120" minHeight="16" minWidth="69" />
        <TableView fx:id="table" layoutX="26.0" layoutY="29.0" prefHeight="221.0" prefWidth="411.0">
            <columns>
                <TableColumn fx:id="firstNameCol" prefWidth="75.0" text="First Name" />
                <TableColumn fx:id="lastNameCol" prefWidth="75.0" text="Last Name" />
                <TableColumn fx:id="emailCol" prefWidth="75.0" text="Email" />
            </columns>
        </TableView>
        <TextField fx:id="addFirstName" layoutX="26.0" layoutY="284.0" prefHeight="25.0" prefWidth="81.0" promptText="First Name" />
        <TextField fx:id="addLastName" layoutX="121.0" layoutY="284.0" prefHeight="25.0" prefWidth="89.0" promptText="Last Name" />
        <TextField fx:id="addEmail" layoutX="222.0" layoutY="284.0" promptText="Email" />
    </children>
</AnchorPane>

My controller code:

package tableviewsample;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;

public class FXMLDocumentController implements Initializable {

    @FXML
    private Label label;

    @FXML
    private TableView<Person> table;// = new TableView<Person>();

    @FXML private TableColumn firstNameCol ;
    @FXML private TableColumn lastNameCol ;
    @FXML private TableColumn emailCol ;

    @FXML TextField addFirstName;
    @FXML TextField addLastName;
    @FXML TextField addEmail;

    private final ObservableList<Person> data
            = FXCollections.observableArrayList(
                    new Person("Jacob", "Smith", "jacob.smith@example.com"),
                    new Person("Isabella", "Johnson", "isabella.johnson@example.com"),
                    new Person("Ethan", "Williams", "ethan.williams@example.com"),
                    new Person("Emma", "Jones", "emma.jones@example.com"),
                    new Person("Michael", "Brown", "michael.brown@example.com")
            );

    @FXML
    private void handleButtonAction(ActionEvent event) {
        System.out.println("You clicked me!");
        data.add(new Person(
                addFirstName.getText(),
                addLastName.getText(),
                addEmail.getText()));
        addFirstName.clear();
        addLastName.clear();
        addEmail.clear();
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // TODO
        firstNameCol.setMinWidth(100);
        lastNameCol.setMinWidth(100);
        emailCol.setMinWidth(200);
        table.getItems().setAll(this.data);
    }

    public static class Person {

        private final SimpleStringProperty firstName;
        private final SimpleStringProperty lastName;
        private final SimpleStringProperty email;

        private Person(String fName, String lName, String email) {
            this.firstName = new SimpleStringProperty(fName);
            this.lastName = new SimpleStringProperty(lName);
            this.email = new SimpleStringProperty(email);
        }

        public String getFirstName() {
            return firstName.get();
        }

        public void setFirstName(String fName) {
            firstName.set(fName);
        }

        public String getLastName() {
            return lastName.get();
        }

        public void setLastName(String fName) {
            lastName.set(fName);
        }

        public String getEmail() {
            return email.get();
        }

        public void setEmail(String fName) {
            email.set(fName);
        }
    }
}

The main code:

package tableviewsample;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class TableViewSample extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }

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

Screenshot:

screenshot

When I run it, there are empty rows in the table. If I type some values in the 3 TextFields and click the button, still the values are not inserted in the table. Can you please find what's wrong with the code? Also, on an unrelated note, how can I make the table scrollable?


回答1:


You haven't set any cellValueFactorys on your TableColumns (Example 12-5 in the tutorial you linked).

You can do this in FXML with

<TableColumn fx:id="firstNameCol" prefWidth="75.0" text="First Name" >
    <cellValueFactory><PropertyValueFactory property="firstName"/></cellValueFactory>
</TableColumn>

or in the controller with

firstNameCol.setCellValueFactory(new PropertyValueFactory("firstName"));

(and similarly for the other columns)




回答2:


You've actually made two mistakes.

First of all, you're trying to assign the datamodel to the TableView using getItems().setAll(). Take a look at the documentation of setAll(). It copies all the values of the given list into the ObservableList. This is not what you want, you want the TableView to start observing data and responding to changes. The way to do this is to assign a reference directly, through setItems(data).

Take a look at the code examples in the documentation of TableView. You forgot to connect the various StringProperties in Person up to the columns. This is the way they do it:

firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));

Lastly, I've got a little sidenote. Note that this is NOT the cause of your specific issue.

I see you're using raw types. This is generally considered a bad thing, and you're probably getting some warnings from the compiler about it. You can solve the issue by stating the generic types your objects use. Notice in the above code sample, I state for the PropertyValueFactories that the type of class contained within the TableView.items is Person and that the type of object displayed in the rows is String.

As for scrolling, which you also asked for, it does that automatically once there are enough lines in the TableView.




回答3:


IN handle Mouse Button you can write: /setItems(); follow the code of green tick above



来源:https://stackoverflow.com/questions/27806367/cant-populate-javafx-tableview-created-in-scenebuilder-2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!