用ArrayList填充TableView(列和数据)

时间:2018-12-06 06:04:19

标签: java intellij-idea javafx tableview fxml

我阅读过的所有页面都显示您必须手动创建tableview列。

我想做的是让tableview自动创建在arrayList中显示类信息所必需的列

因此,如果我更改播放器类以存储更多信息(例如生日),则不必更改表视图,它只会自动更新。

package Homework_5;

public class Player {
    private String firstName;
    private String lastName;
    private int age;

    public Player(String firstName, String lastName, int age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }

    public String GetFirstName() {
        return firstName;
    }

    public String GetLastName() {
        return lastName;
    }

    public int GetAge(){
        return age;
    }
}

控制器

package Homework_5.FXML_Java_Classes;

imports

public class ViewPlayers {

    @FXML // fx:id="tablePlayers"
    private TableView<Player> tablePlayers; // Value injected by FXMLLoader

    @FXML // fx:id="btnDeletePlayer"
    private Button btnDeletePlayer; // Value injected by FXMLLoader

    @FXML // fx:id="pieChartWin"
    private PieChart pieChartWin; // Value injected by FXMLLoader

    @FXML // fx:id="btnAddPlayer"
    private Button btnAddPlayer; // Value injected by FXMLLoader

    @FXML // fx:id="root"
    private Parent root; // Value injected by FXMLLoader

    ArrayList<Player> players;
    ArrayList<Connect4Game> games;

    public ViewPlayers(){

    }

    public ViewPlayers create() {
        try {
            FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("../FXML_Files/ViewPlayers.fxml"));
            fxmlLoader.load();
            return fxmlLoader.getController();
        } catch (Exception e)
        {
            e.printStackTrace();
        }
        return null;
    }

    public void Show(ArrayList<Connect4Game> games, ArrayList<Player> players)
    {
        this.games = games;
        this.players = players;

        RefreshTable();

        Stage stage = new Stage();
        stage.initModality(Modality.WINDOW_MODAL);
        stage.setTitle("Enter Player Information");
        stage.setScene(new Scene(root));
        stage.showAndWait();
    }

    @FXML
    void AddPlayer(ActionEvent event) {
        PlayerInfo playerInfo = new PlayerInfo().create();
        playerInfo.Show();
        players.add(new Player(playerInfo.getTxtName(), playerInfo.getColor(), playerInfo.getChkComputer()));
        RefreshTable();
    }

    @FXML
    void DeletePlayer(ActionEvent event) {
        players.remove(tablePlayers.getSelectionModel().getSelectedItem());
        RefreshTable();
    }

    @FXML
    void PlayerSelected(ActionEvent event) {
        if (tablePlayers.getItems().size() == 0) return;

        int won = 0;
        int lost = 0;
        Player player = tablePlayers.getSelectionModel().getSelectedItem();

        for(Connect4Game game : games)
        {
            if (game.getWinner() == player) {
                won++;
            } else {
                lost++;
            }
        }

        ObservableList<PieChart.Data> pieCharData = FXCollections.observableArrayList(
                new PieChart.Data("Won", won),
                new PieChart.Data("Lost", lost));
    }

    private void RefreshTable() {
        ObservableList<Player> players = FXCollections.observableArrayList(this.players);
        tablePlayers.getItems().clear();
        tablePlayers.getItems().addAll(players);
    }
}

1 个答案:

答案 0 :(得分:0)

巧合的是,我今天也一样。我想出了以下解决方案。我认为这不是最好的,但到目前为止,它的设计还不够完善。但是那辛苦的工作。

您可以使用Reflection来确定类的字段,并添加一个tableColumn,如下所示:

Field[] fields = Player.class.getDeclaredFields();
for (Field f : fields)
{
    TableColumn<DatabaseItem, Object> tblColumn = new TableColumn<>(f.getName());
    tblColumn.setCellValueFactory(new PropertyValueFactory<Player, Object>(f.getName()));
    tblView.getColumns().add(tblColumn);
}

现在,您可以使用自定义注释来扩展可见性,标题名称和优先级:

@Retention(RUNTIME)
@Target(FIELD)
public @interface DynTableColumn
{
    boolean visible() default false;

    String header() default "N/V";

    int prio() default Integer.MAX_VALUE;
}

播放器:

public class Player 
{
    @DynTableColumn(visible = true, header = "First Name", prio = 10)
    private String firstName;
    @DynTableColumn(visible = true, header = "Last Name", prio = 20)
    private String lastName;
    @DynTableColumn(visible = true, header = "Age", prio = 30)
    private int age;

    [..]
}

并修改上面的代码:

private void setTableColumns()
{
    Field[] fields = item.getClass().getDeclaredFields();
    List<TableColumn<DatabaseItem, Object>> columns = new ArrayList<>();

    for (Field f : prepareField(fields))
    {
        DynTableColumn annotation = f.getAnnotation(DynTableColumn.class);

        TableColumn<DatabaseItem, Object> tblColumn = new TableColumn<>(annotation.header());
        tblColumn.setCellValueFactory(new PropertyValueFactory<DatabaseItem, Object>(f.getName()));
        columns.add(tblColumn);
    }

    tblView.getColumns().addAll(columns);
}

private Field[] prepareField(Field[] fieldToPrepare)
{
    return sortFieldByAnnotation(filterFieldByAnnotatedFields(fieldToPrepare));
}

public Field[] sortFieldByAnnotation(Field[] fieldsToSort)
{
    class sortByAnnotationPrio implements Comparator<Field>
    {

        @Override
        public int compare(Field o1, Field o2)
        {
            DynTableColumn a1 = o1.getAnnotation(DynTableColumn.class);
            DynTableColumn a2 = o2.getAnnotation(DynTableColumn.class);
            return a1.prio() - a2.prio();
        }

    }

    Arrays.sort(fieldsToSort, new sortByAnnotationPrio());
    return fieldsToSort;
}

public Field[] filterFieldByAnnotatedFields(Field[] fieldsToFilter)
{
    Field[] filteredFields = new Field[fieldsToFilter.length];

    int i = 0;
    for (Field f : fieldsToFilter)
    {
        if (f.isAnnotationPresent(DynTableColumn.class))
        {
            filteredFields[i] = f;
            i++;
        }
    }

    return removeNullValues(filteredFields);
}

private Field[] removeNullValues(Field[] fieldsToFilter)
{
    List<Field> list = new ArrayList<Field>();

    for (Field f : fieldsToFilter)
    {
        if (f != null)
        {
            list.add(f);
        }
    }

    return list.toArray(new Field[list.size()]);
}