我已经阅读了几个关于使用Properties在JavaFX TableView中显示数据的线程,我可以使所有这些工作正常。到目前为止,我一直在没有问题的TableView中显示数据而没有问题。但是,继续前进我认为我需要开始使用Properties,特别是因为我希望我的TableView可以编辑。我怀疑问题是因为我看过的所有例子都使用一个对象来显示1行数据,而在我的模型中我每个单元格有一个对象(一个Field
对象),但我想不出为什么这应该是一个问题。
以下是我的Field
类的非常简化的版本,足以进行此测试,但还不足以显示其实际用途。我还有一个测试类TableViewDemo
。任何有关这个令人厌烦的问题的帮助将非常感激。要么是愚蠢的错误,要么是我设计的根本问题。
package javafxtest;
import java.sql.SQLException;
import javafx.beans.property.SimpleObjectProperty;
public class Field {
private final SimpleObjectProperty objectValue; //All the data is stored as an object, then cast to appropriate data type
public Field(Object objValue) throws SQLException {
if (objValue == null) {
throw new SQLException("Field value is null");
}
this.objectValue = new SimpleObjectProperty(objValue);
}
public final String getStringValue() {
return (String) this.objectValue.get();
}
public final int getIntValue() {
return (Integer) this.objectValue.get();
}
public final double getDoubleValue() {
return (Double) this.objectValue.get();
}
public final boolean getBooleanValue() {
return (Boolean) this.objectValue.get();
}
}
package javafxtest;
import java.sql.SQLException;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;
public class TableViewDemo extends Application {
@Override
public void start(Stage myStage) {
// Set up the stage
myStage.setTitle("Demonstrate TableView");
FlowPane rootNode = new FlowPane(10, 10);
rootNode.setAlignment(Pos.CENTER);
Scene myScene = new Scene(rootNode, 600, 450);
myStage.setScene(myScene);
//Set up some test data - 4 rows of 4 columns
ObservableList<Field[]> dataModel = FXCollections.observableArrayList();
ObservableList<Field[]> dataModel2 = FXCollections.observableArrayList();
Field[] fields1;
Field[] fields2;
Field[] fields3;
Field[] fields4;
try {
fields1 = new Field[4];
fields1[0] = new Field("R1C1");
fields1[1] = new Field(25);
fields1[2] = new Field(100.00);
fields1[3] = new Field(true);
fields2 = new Field[4];
fields2[0] = new Field("R2C1");
fields2[1] = new Field(30);
fields2[2] = new Field(150.00);
fields2[3] = new Field(false);
fields3 = new Field[4];
fields3[0] = new Field("R3C1");
fields3[1] = new Field(397);
fields3[2] = new Field(1005.99);
fields3[3] = new Field(true);
fields4 = new Field[4];
fields4[0] = new Field("R4C1");
fields4[1] = new Field(1085);
fields4[2] = new Field(1.00);
fields4[3] = new Field(false);
//Add the data to the dataModel
dataModel.addAll(fields1, fields2, fields3, fields4);
//Set up the columns ===== This is where the likely problem is, or at least part of the problem ====
TableColumn<Field[], String> colString = new TableColumn<>("String");
colString.setCellValueFactory(new PropertyValueFactory<>("stringValue"));
colString.setPrefWidth(150);
TableColumn<Field[], Integer> colInt = new TableColumn<>("int");
colInt.setCellValueFactory(new PropertyValueFactory<>("intValue"));
colInt.setPrefWidth(100);
TableColumn<Field[], Double> colDouble = new TableColumn<>("double");
colDouble.setCellValueFactory(new PropertyValueFactory<>("doubleValue"));
colDouble.setPrefWidth(100);
TableColumn<Field[], Boolean> colBoolean = new TableColumn<>("boolean");
colBoolean.setCellValueFactory(new PropertyValueFactory<>("booleanValue"));
colBoolean.setPrefWidth(75);
//Set up the TableView - it takes an Array of Field objects. Add the data and columns to it
TableView<Field[]> tableView = new TableView<Field[]>();
tableView.setItems(dataModel);
tableView.getColumns().addAll(colString, colInt, colDouble, colBoolean);
//Print out the datamodel
dataModel2 = tableView.getItems();
for (int i = 0; i < dataModel2.size(); i++) {
Field[] fields = new Field[4];
fields = dataModel2.get(i);
for (int j = 0; j < fields.length; j++) {
Field field = fields[j];
switch (j) {
case 0: //Column is a String data type
System.out.println(field.getStringValue());
break;
case 1: //Column is a int data type
System.out.println(field.getIntValue());
break;
case 2: //Column is a double data type
System.out.println(field.getDoubleValue());
break;
case 3: //Column is a boolean data type
System.out.println(field.getBooleanValue());
break;
default:
break;
}
}
}
// Set the tableView size
tableView.setPrefWidth(500);
tableView.setPrefHeight(300);
rootNode.getChildren().add(tableView);
} catch (SQLException e) {
System.out.println(e.getLocalizedMessage());
}
myStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
这是我目前使用String值填充单元格的原因:
final int x = i;
tableColumn<Field[], String> columnString = (TableColumn<Field[], String>) this.columnModel.get(i);
columnString.setCellValueFactory((TableColumn.CellDataFeatures<Field[], String> fieldArray) -> {
Field arrayField = fieldArray.getValue()[x];
return new ReadOnlyObjectWrapper(arrayField.getStringValue());
});
答案 0 :(得分:0)
这根本不是UnZipAssets("gameModLevels.zip", Path.Combine(Application.Context.CacheDir.AbsolutePath, "assets"));
的工作方式。来自documentation:
如何使用此类的示例如下:
PropertyValueFactory
在此示例中,
TableColumn<Person,String> firstNameCol = new TableColumn<Person,String>("First Name"); firstNameCol.setCellValueFactory(new PropertyValueFactory<Person,String>("firstName"));
是Person
项列表的类类型。必须将类TableView
声明为public。Person
使用构造函数参数PropertyValueFactory
来假设"firstName"
的公共方法Person
没有正式参数且返回类型为firstNameProperty
。如果存在这样的方法,则调用它,并且还假设返回
ObservableValue<String>
的实例。返回值用于填充Property<String>
。此外,TableCell
会在返回值中添加一个观察者,以便TableView
可以观察到触发的任何更改,从而导致单元格立即更新。如果不存在此类方法,则
TableView
会假定PropertyValueFactory
具有公共方法Person
或getFirstName
,且没有正式参数且返回类型为{{1} }。如果存在这样的方法,则调用它,并将其返回值包装在isFirstName
中并返回到String
。
因此,基本上,ReadOnlyObjectWrapper
检索表示行的对象,并使用反射来查找方法TableCell
,其中PropertyValueFactory
是分配给{{1}的属性名称}}。如果不存在这样的方法,则作为后退,它会查找方法xxxProperty()
,并将结果(如果存在)包装在xxx
中。
在您的情况下,表示该行的值为PropertyValueFactory
,即该对象是getXxx()
的数组。数组没有ReadOnlyObjectWrapper
或Field[]
方法(等),因此失败。 (当然,数组的各个元素都有这些方法,但Field
不会查看数组元素,它只是查看行的值,即数组本身。)
很难知道如何解决&#34;这个问题,因为没有明显的理由你不想以这种方式处理事情。当然,你可以做到
stringValueProperty()
等等,但在那一点上,你不清楚为什么你不会只定义一个有四个常规字段的类 - 或者甚至只是使用一个getStringValue()
来摆脱你的{{ 1}} class - 无论如何。