为了使用TableView,是否需要为每个数据库查询创建类?
在过去的几天里,我学习了一些关于JavaFX的教程,解释如何使用TableView?每个教程都为example创建了类似
Person
的DataModel对象。只要您只需要像select Firstname, Lastname from Person
这样的SQL语句就可以了。
但是,如果您不想为每个SELECT查询创建数据模型,因为您出于某种原因将数据与其他对象联接起来,该怎么办呢?例如,select * from Person join City join Country
。前几天我学到的是,如果创建一个只包含List
(表示行)的表视图,处理格式甚至计算表视图都会变得很糟糕。
这真的是JavaFX的事情吗?还是我错过了什么?
更新
为了更清楚,请参阅question。我是在阅读对我的问题的回答和评论后首次发现此问题的,但我对链接问题的答案不满意。
SQL
您的问题在这里混淆了两个概念:一方面是javafx.scene.control.TableView
,另一方面是推荐答案/ORM。让我们忘掉SQL查询,比如我认为您最关心的是TableView
。
TableView
必须填充List
。此列表的内部类型必须与TableView的泛型类型匹配。因此,例如TableView<Person>
将使用List<Person>
填充。
除此之外,表示行的对象的实际类型可以是任何类型。它甚至不必包含数据本身,或者它可以是一个Map<String, Object>
。在本例中,您将通过为每一列定义一个CellValueFactory
来将该行的键映射到每一列,该CellValueFactory
将返回您选择的键的入口值。
然后,您可以通过为列定义CellFactory
将此值转换为String
和/或Node
。
具有JavaFX属性的对象可以更容易地映射,因为存在仅需要属性名称的预制PropertyValueFactory
。但它们并不是唯一的出路。
为每行使用Map<String, Object>
的示例:
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javafx.application.Application;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class App extends Application {
private TableView<Map<String, Object>> tableView;
private TableColumn<Map<String, Object>, String> nameCol;
private TableColumn<Map<String, Object>, Integer> ageCol;
private Stage stage;
@Override
public void start(Stage stage) {
this.stage = stage;
//Insert a TableView into scene
this.tableView = new TableView<>();
this.nameCol = new TableColumn<>("Name");
this.nameCol.setPrefWidth(250);
ageCol = new TableColumn<>("Age");
tableView.getColumns().add(nameCol);
tableView.getColumns().add(ageCol);
nameCol.setCellValueFactory(param -> {
Map<String, Object> v = param.getValue();
return new SimpleStringProperty(v == null ? null : (String) v.get("name"));
});
ageCol.setCellValueFactory(param -> {
Map<String, Object> v = param.getValue();
return new SimpleObjectProperty<Integer>(v == null ? null : (Integer) v.get("age"));
});
ageCol.setCellFactory(param -> {
return new TableCell<>() {
@Override
public void updateItem(Integer item, boolean empty) {
if (empty || item == null)
super.setText("");
else
super.setText(NumberFormat.getIntegerInstance().format(item));
//Could also call setGraphic(Node)
}
};
});
final Scene scene = new Scene(new BorderPane(tableView), 640, 480);
stage.setScene(scene);
stage.setOnShown(event -> stageReady()); //Continue when stage is rendered
stage.show();
}
private void stageReady() {
//Generate data
List<Map<String, Object>> data = new ArrayList<>();
Map<String, Object> obj1 = new HashMap<>();
obj1.put("name", "Name of Object 1");
obj1.put("age", 42);
data.add(obj1);
Map<String, Object> obj2 = new HashMap<>();
obj2.put("name", "OBJECT 2");
obj2.put("age", 53);
data.add(obj2);
//Show data
tableView.getItems().setAll(data);
}
public static void main(String[] args) {
launch();
}
}
ageCol.setCellFactory
仅用于演示。如果我没有设置它,则Integer
单元格将呈现为调用Integer.toString()
单元格text
属性。
相关文章