tableView(JavaFX) 完整形式的 ObservableList 不工作
tableView(JavaFX) fill from ObservableList dont working
我正在尝试从数据 (ObservableList) 中填充 tableview2(fx:id tableview) 行。但是当它完成时,tableview2 只显示空记录。在控制台中,我看到数据(ObservableList)中的所有行。我知道在 Whosebug 中有很多关于这个的问题,对此(和我的英语)感到抱歉,但是请问我代码中的错误在哪里?感谢您的帮助或关注)。
更新(添加 MainPayer.java 并更新 PayerController.java):
这是我的代码。
PayerController.java:
public class PayerController {
@FXML
private TableColumn<MainPayer,Long> tablePayerid2;
@FXML
private TableColumn<MainPayer,Long> tableIsAccepted2;
@FXML
private TableColumn<MainPayer,Long> tableYear2;
@FXML
private TableColumn<MainPayer,Long> tableQuater2;
@FXML
private TableColumn<MainPayer,Long> tableEnspeopley2;
@FXML
private TableColumn<MainPayer,String> tableShortName2;
@FXML
private TableColumn<MainPayer,String> tableDistrict2;
@FXML
private TableColumn<MainPayer,String> tableSettlement2;
@FXML
private TableColumn<MainPayer,String> tableStreet2;
@FXML
private TableColumn<MainPayer,String> tableHouseNum2;
@FXML
private TableColumn<MainPayer,String> tableMailIndex2;
@FXML
private TableView<MainPayer> tableview2;
private ObservableList<MainPayer> data;
@FXML
private void handleRunMainQuery() throws SQLException {
Connection dbConnection = null;
Statement statement = null;
String selectTableSQL = "SELECT F.PAYERID, F.ISACCEPTED, F.RYEAR, F.QUATER, F.ENSPEOPLEY, S.CSHORTNAME, T.DISTRICT, T.SETTLEMENT, T.STREETNAME, T.HOUSENUM, \n" +
" T.MAILINDEX\n" +
"FROM FFUNDSIDE F, FPAYER S, FLOCATIONHISTORY T,\n" +
" (SELECT PAYERID, MAX(LADATE) AS LADATE\n" +
" FROM FLOCATIONHISTORY\n" +
" GROUP BY PAYERID) X\n" +
"WHERE F.PAYERID = S.PAYERID AND S.PAYERID = T.PAYERID AND T.PAYERID = X.PAYERID AND T.LADATE = X.LADATE AND (F.PAYERID BETWEEN \n" +
" 400000000 AND 499999999) AND (F.RYEAR = 2018) AND (F.QUATER = 3) AND (F.ENSPEOPLEY > 10)";
data = FXCollections.observableArrayList();
try {
dbConnection = getDBConnection();
statement = dbConnection.createStatement();
ResultSet rs = statement.executeQuery(selectTableSQL);
tablePayerid2.setCellValueFactory(data -> data.getValue().payerid2Property().asObject());
tableIsAccepted2.setCellValueFactory(data -> data.getValue().isAccepted2Property().asObject());
tableYear2.setCellValueFactory(data -> data.getValue().year2Property().asObject());
tableQuater2.setCellValueFactory(data -> data.getValue().quater2Property().asObject());
tableEnspeopley2.setCellValueFactory(data -> data.getValue().enspeopley2Property().asObject());
tableShortName2.setCellValueFactory(data -> data.getValue().shortName2Property());
tableDistrict2.setCellValueFactory(data -> data.getValue().district2Property());
tableSettlement2.setCellValueFactory(data -> data.getValue().settlement2Property());
tableStreet2.setCellValueFactory(data -> data.getValue().street2Property());
tableHouseNum2.setCellValueFactory(data -> data.getValue().houseNum2Property());
tableMailIndex2.setCellValueFactory(data -> data.getValue().mailIndex2Property());
while (rs.next()) {
ObservableList<MainPayer> row = FXCollections.observableArrayList();
data.add(new MainPayer(rs.getLong(1),rs.getLong(2),rs.getLong(3),rs.getLong(4),rs.getLong(5),
rs.getString(6),rs.getString(7),rs.getString(8),rs.getString(9),rs.getString(10),
rs.getString(11)));
}
tableview2.setItems(data);
} catch (SQLException e) {
System.out.println(e.getMessage());
} finally {
if (statement != null) {
statement.close();
}
if (dbConnection != null) {
dbConnection.close();
}
}
}
MainPayer.java
public class MainPayer {
private final LongProperty payerid2;
private final LongProperty isAccepted2;
private final LongProperty year2;
private final LongProperty quater2;
private final LongProperty enspeopley2;
private final StringProperty shortName2;
private final StringProperty district2;
private final StringProperty settlement2;
private final StringProperty street2;
private final StringProperty houseNum2;
private final StringProperty mailIndex2;
public MainPayer(Long payerid2, Long isAccepted2, Long year2, Long quater2, Long enspeopley2, String shortName2, String district2,
String settlement2, String street2, String houseNum2, String mailIndex2) {
this.payerid2 = new SimpleLongProperty(payerid2);
this.isAccepted2 = new SimpleLongProperty(isAccepted2);
this.year2 = new SimpleLongProperty(year2);
this.quater2 = new SimpleLongProperty(quater2);
this.enspeopley2 = new SimpleLongProperty(enspeopley2);
this.shortName2 = new SimpleStringProperty(shortName2);
this.district2 = new SimpleStringProperty(district2);
this.settlement2 = new SimpleStringProperty(settlement2);
this.street2 = new SimpleStringProperty(street2);
this.houseNum2 = new SimpleStringProperty(houseNum2);
this.mailIndex2 = new SimpleStringProperty(mailIndex2);
}
public LongProperty payerid2Property() {
return payerid2;
}
public LongProperty isAccepted2Property() {
return isAccepted2;
}
public LongProperty year2Property() {
return year2;
}
public LongProperty quater2Property() {
return quater2;
}
public LongProperty enspeopley2Property() {
return enspeopley2;
}
public StringProperty shortName2Property() {
return shortName2;
}
public StringProperty district2Property() {
return district2;
}
public StringProperty settlement2Property() {
return settlement2;
}
public StringProperty street2Property() {
return street2;
}
public StringProperty houseNum2Property() {
return houseNum2;
}
public StringProperty mailIndex2Property() {
return mailIndex2;
}
}
MainScene.fxml
<TableView fx:id="tableview2" layoutX="210.0" layoutY="72.0" prefHeight="345.0" prefWidth="981.0">
<placeholder>
<Label text="Go ahead" />
</placeholder>
<columns>
<TableColumn fx:id="tablePayerid2" minWidth="20.0" prefWidth="104.0" text="A" />
<TableColumn fx:id="tableIsAccepted2" minWidth="40.0" prefWidth="74.0" text="B" />
<TableColumn fx:id="tableYear2" minWidth="1.0" prefWidth="75.0" text="C" />
<TableColumn fx:id="tableQuater2" minWidth="1.0" prefWidth="75.0" text="D" />
<TableColumn fx:id="tableEnspeopley2" minWidth="15.0" prefWidth="75.0" text="E" />
<TableColumn fx:id="tableShortName2" minWidth="15.0" prefWidth="75.0" text="F" />
<TableColumn fx:id="tableDistrict2" prefWidth="75.0" text="J" />
<TableColumn fx:id="tableSettlement2" prefWidth="75.0" text="K" />
<TableColumn fx:id="tableStreet2" prefWidth="111.0" text="L" />
<TableColumn fx:id="tableHouseNum2" minWidth="1.0" prefWidth="67.0" text="M" />
<TableColumn fx:id="tableMailIndex2" minWidth="2.0" prefWidth="58.0" text="N" />
</columns>
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
</TableView>
您遇到了一些问题。
首先,您应该了解 TableView
如何在 JavaFx 中工作的基本概念。
除了链接教程,也许我可以指出您错过了什么,以及如何解决这些问题。
简单解释一下 TableView
有两个 "parts" 一个是 UI 部分,您可以看到它包含列,headers、行等。另一侧是填充 table 的 模型 。创建 UI 端后,您必须将模型分配给 table 以获得添加到 table 的预期数据。
在 TableView
中,一行不是项目列表,而是模型的一个实例,每个列都有字段。 (当然它可以是一个列表,但对你来说它会让事情变得更复杂)
有几个步骤,如果你尊重你可以得到预期的结果:
- 创建一个 calass 作为 模型,代表您拥有的数据。在你的情况下,我看到有一个用户或从数据库加载的东西,所以也许你可以创建一个
User
class,其中包含你想从数据库加载的字段,如 palayerId、isAccepted、年份等。
每个字段都应该是一个Property
对应它的类型,如果是String就应该是StringProperty,如果是long就应该是LongProperty,等等。
将此模型作为通用模型传递给 TableView
,就像您拥有的一样:private TableView tableView2
-> private TableView<User> tableView2
所以 table 中的每一行都是用户的一个实例,你可以像你试过的那样在 ObservableList 中定义整个 table 数据,ObservableList<User> data
然后像你一样 table.setItems(data)
.
- 现在 table 知道 数据,但列还不知道,所以你必须 告诉 每一列哪些数据属于它。您必须像为 table 视图所做的那样为每一列创建一个
@FXML
字段,并且 告诉 它必须显示哪些数据的每一列,例如:
假设您有一个包含字符串的列:
@FXML
private TableColumn<User,String> colWithString;
然后你可以告诉它像:
colWithString.setCellValueFactory(data -> data.getValue().myStringProperty());
而不是 myStringProperty
当然,你把合适的 属性 放在需要的地方。
- 在 for 循环中,您只需将
User
的新实例添加到您之前创建的 data
中,例如:data.add(new User(rs.getString(1),rs.getString(2),rs.getLong(3),...))
仅此而已,如果您遵循这些步骤并相应地进行修改,则应显示来自数据库的数据。
我正在尝试从数据 (ObservableList) 中填充 tableview2(fx:id tableview) 行。但是当它完成时,tableview2 只显示空记录。在控制台中,我看到数据(ObservableList)中的所有行。我知道在 Whosebug 中有很多关于这个的问题,对此(和我的英语)感到抱歉,但是请问我代码中的错误在哪里?感谢您的帮助或关注)。
更新(添加 MainPayer.java 并更新 PayerController.java): 这是我的代码。
PayerController.java:
public class PayerController {
@FXML
private TableColumn<MainPayer,Long> tablePayerid2;
@FXML
private TableColumn<MainPayer,Long> tableIsAccepted2;
@FXML
private TableColumn<MainPayer,Long> tableYear2;
@FXML
private TableColumn<MainPayer,Long> tableQuater2;
@FXML
private TableColumn<MainPayer,Long> tableEnspeopley2;
@FXML
private TableColumn<MainPayer,String> tableShortName2;
@FXML
private TableColumn<MainPayer,String> tableDistrict2;
@FXML
private TableColumn<MainPayer,String> tableSettlement2;
@FXML
private TableColumn<MainPayer,String> tableStreet2;
@FXML
private TableColumn<MainPayer,String> tableHouseNum2;
@FXML
private TableColumn<MainPayer,String> tableMailIndex2;
@FXML
private TableView<MainPayer> tableview2;
private ObservableList<MainPayer> data;
@FXML
private void handleRunMainQuery() throws SQLException {
Connection dbConnection = null;
Statement statement = null;
String selectTableSQL = "SELECT F.PAYERID, F.ISACCEPTED, F.RYEAR, F.QUATER, F.ENSPEOPLEY, S.CSHORTNAME, T.DISTRICT, T.SETTLEMENT, T.STREETNAME, T.HOUSENUM, \n" +
" T.MAILINDEX\n" +
"FROM FFUNDSIDE F, FPAYER S, FLOCATIONHISTORY T,\n" +
" (SELECT PAYERID, MAX(LADATE) AS LADATE\n" +
" FROM FLOCATIONHISTORY\n" +
" GROUP BY PAYERID) X\n" +
"WHERE F.PAYERID = S.PAYERID AND S.PAYERID = T.PAYERID AND T.PAYERID = X.PAYERID AND T.LADATE = X.LADATE AND (F.PAYERID BETWEEN \n" +
" 400000000 AND 499999999) AND (F.RYEAR = 2018) AND (F.QUATER = 3) AND (F.ENSPEOPLEY > 10)";
data = FXCollections.observableArrayList();
try {
dbConnection = getDBConnection();
statement = dbConnection.createStatement();
ResultSet rs = statement.executeQuery(selectTableSQL);
tablePayerid2.setCellValueFactory(data -> data.getValue().payerid2Property().asObject());
tableIsAccepted2.setCellValueFactory(data -> data.getValue().isAccepted2Property().asObject());
tableYear2.setCellValueFactory(data -> data.getValue().year2Property().asObject());
tableQuater2.setCellValueFactory(data -> data.getValue().quater2Property().asObject());
tableEnspeopley2.setCellValueFactory(data -> data.getValue().enspeopley2Property().asObject());
tableShortName2.setCellValueFactory(data -> data.getValue().shortName2Property());
tableDistrict2.setCellValueFactory(data -> data.getValue().district2Property());
tableSettlement2.setCellValueFactory(data -> data.getValue().settlement2Property());
tableStreet2.setCellValueFactory(data -> data.getValue().street2Property());
tableHouseNum2.setCellValueFactory(data -> data.getValue().houseNum2Property());
tableMailIndex2.setCellValueFactory(data -> data.getValue().mailIndex2Property());
while (rs.next()) {
ObservableList<MainPayer> row = FXCollections.observableArrayList();
data.add(new MainPayer(rs.getLong(1),rs.getLong(2),rs.getLong(3),rs.getLong(4),rs.getLong(5),
rs.getString(6),rs.getString(7),rs.getString(8),rs.getString(9),rs.getString(10),
rs.getString(11)));
}
tableview2.setItems(data);
} catch (SQLException e) {
System.out.println(e.getMessage());
} finally {
if (statement != null) {
statement.close();
}
if (dbConnection != null) {
dbConnection.close();
}
}
}
MainPayer.java
public class MainPayer {
private final LongProperty payerid2;
private final LongProperty isAccepted2;
private final LongProperty year2;
private final LongProperty quater2;
private final LongProperty enspeopley2;
private final StringProperty shortName2;
private final StringProperty district2;
private final StringProperty settlement2;
private final StringProperty street2;
private final StringProperty houseNum2;
private final StringProperty mailIndex2;
public MainPayer(Long payerid2, Long isAccepted2, Long year2, Long quater2, Long enspeopley2, String shortName2, String district2,
String settlement2, String street2, String houseNum2, String mailIndex2) {
this.payerid2 = new SimpleLongProperty(payerid2);
this.isAccepted2 = new SimpleLongProperty(isAccepted2);
this.year2 = new SimpleLongProperty(year2);
this.quater2 = new SimpleLongProperty(quater2);
this.enspeopley2 = new SimpleLongProperty(enspeopley2);
this.shortName2 = new SimpleStringProperty(shortName2);
this.district2 = new SimpleStringProperty(district2);
this.settlement2 = new SimpleStringProperty(settlement2);
this.street2 = new SimpleStringProperty(street2);
this.houseNum2 = new SimpleStringProperty(houseNum2);
this.mailIndex2 = new SimpleStringProperty(mailIndex2);
}
public LongProperty payerid2Property() {
return payerid2;
}
public LongProperty isAccepted2Property() {
return isAccepted2;
}
public LongProperty year2Property() {
return year2;
}
public LongProperty quater2Property() {
return quater2;
}
public LongProperty enspeopley2Property() {
return enspeopley2;
}
public StringProperty shortName2Property() {
return shortName2;
}
public StringProperty district2Property() {
return district2;
}
public StringProperty settlement2Property() {
return settlement2;
}
public StringProperty street2Property() {
return street2;
}
public StringProperty houseNum2Property() {
return houseNum2;
}
public StringProperty mailIndex2Property() {
return mailIndex2;
}
}
MainScene.fxml
<TableView fx:id="tableview2" layoutX="210.0" layoutY="72.0" prefHeight="345.0" prefWidth="981.0">
<placeholder>
<Label text="Go ahead" />
</placeholder>
<columns>
<TableColumn fx:id="tablePayerid2" minWidth="20.0" prefWidth="104.0" text="A" />
<TableColumn fx:id="tableIsAccepted2" minWidth="40.0" prefWidth="74.0" text="B" />
<TableColumn fx:id="tableYear2" minWidth="1.0" prefWidth="75.0" text="C" />
<TableColumn fx:id="tableQuater2" minWidth="1.0" prefWidth="75.0" text="D" />
<TableColumn fx:id="tableEnspeopley2" minWidth="15.0" prefWidth="75.0" text="E" />
<TableColumn fx:id="tableShortName2" minWidth="15.0" prefWidth="75.0" text="F" />
<TableColumn fx:id="tableDistrict2" prefWidth="75.0" text="J" />
<TableColumn fx:id="tableSettlement2" prefWidth="75.0" text="K" />
<TableColumn fx:id="tableStreet2" prefWidth="111.0" text="L" />
<TableColumn fx:id="tableHouseNum2" minWidth="1.0" prefWidth="67.0" text="M" />
<TableColumn fx:id="tableMailIndex2" minWidth="2.0" prefWidth="58.0" text="N" />
</columns>
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
</TableView>
您遇到了一些问题。
首先,您应该了解 TableView
如何在 JavaFx 中工作的基本概念。
除了链接教程,也许我可以指出您错过了什么,以及如何解决这些问题。
简单解释一下 TableView
有两个 "parts" 一个是 UI 部分,您可以看到它包含列,headers、行等。另一侧是填充 table 的 模型 。创建 UI 端后,您必须将模型分配给 table 以获得添加到 table 的预期数据。
在 TableView
中,一行不是项目列表,而是模型的一个实例,每个列都有字段。 (当然它可以是一个列表,但对你来说它会让事情变得更复杂)
有几个步骤,如果你尊重你可以得到预期的结果:
- 创建一个 calass 作为 模型,代表您拥有的数据。在你的情况下,我看到有一个用户或从数据库加载的东西,所以也许你可以创建一个
User
class,其中包含你想从数据库加载的字段,如 palayerId、isAccepted、年份等。 每个字段都应该是一个Property
对应它的类型,如果是String就应该是StringProperty,如果是long就应该是LongProperty,等等。 将此模型作为通用模型传递给
TableView
,就像您拥有的一样:private TableView tableView2
->private TableView<User> tableView2
所以 table 中的每一行都是用户的一个实例,你可以像你试过的那样在 ObservableList 中定义整个 table 数据,
ObservableList<User> data
然后像你一样table.setItems(data)
.- 现在 table 知道 数据,但列还不知道,所以你必须 告诉 每一列哪些数据属于它。您必须像为 table 视图所做的那样为每一列创建一个
@FXML
字段,并且 告诉 它必须显示哪些数据的每一列,例如:
假设您有一个包含字符串的列:
@FXML
private TableColumn<User,String> colWithString;
然后你可以告诉它像:
colWithString.setCellValueFactory(data -> data.getValue().myStringProperty());
而不是 myStringProperty
当然,你把合适的 属性 放在需要的地方。
- 在 for 循环中,您只需将
User
的新实例添加到您之前创建的data
中,例如:data.add(new User(rs.getString(1),rs.getString(2),rs.getLong(3),...))
仅此而已,如果您遵循这些步骤并相应地进行修改,则应显示来自数据库的数据。