我阅读过的所有页面都显示您必须手动创建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);
}
}
答案 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()]);
}